diff options
| author | glic3rinu | 2013-03-27 22:43:41 +0100 | 
|---|---|---|
| committer | glic3rinu | 2013-03-27 22:43:41 +0100 | 
| commit | 5f48b4a77e0a767694a32310a6368cd32b9a924c (patch) | |
| tree | 081556c5f646c49eca6abcece28cb4a81983ab5a /rest_framework | |
| parent | 9b56616750bc769a3a5172f8f7603153c9335685 (diff) | |
| download | django-rest-framework-5f48b4a77e0a767694a32310a6368cd32b9a924c.tar.bz2 | |
Refactored urlize_quoted_links code, now based on Django 1.5 urlize
Diffstat (limited to 'rest_framework')
| -rw-r--r-- | rest_framework/templatetags/rest_framework.py | 79 | 
1 files changed, 45 insertions, 34 deletions
diff --git a/rest_framework/templatetags/rest_framework.py b/rest_framework/templatetags/rest_framework.py index c21ddcd7..50e485db 100644 --- a/rest_framework/templatetags/rest_framework.py +++ b/rest_framework/templatetags/rest_framework.py @@ -2,7 +2,7 @@ from __future__ import unicode_literals, absolute_import  from django import template  from django.core.urlresolvers import reverse, NoReverseMatch  from django.http import QueryDict -from django.utils.html import escape +from django.utils.html import escape, smart_urlquote  from django.utils.safestring import SafeData, mark_safe  from rest_framework.compat import urlparse  from rest_framework.compat import force_text @@ -112,22 +112,6 @@ def replace_query_param(url, key, val):  class_re = re.compile(r'(?<=class=["\'])(.*)(?=["\'])') -# Bunch of stuff cloned from urlize -LEADING_PUNCTUATION = ['(', '<', '<', '"', "'"] -TRAILING_PUNCTUATION = ['.', ',', ')', '>', '\n', '>', '"', "'"] -DOTS = ['·', '*', '\xe2\x80\xa2', '•', '•', '•'] -unencoded_ampersands_re = re.compile(r'&(?!(\w+|#\d+);)') -word_split_re = re.compile(r'(\s+)') -punctuation_re = re.compile('^(?P<lead>(?:%s)*)(?P<middle>.*?)(?P<trail>(?:%s)*)$' % \ -    ('|'.join([re.escape(x) for x in LEADING_PUNCTUATION]), -    '|'.join([re.escape(x) for x in TRAILING_PUNCTUATION]))) -simple_email_re = re.compile(r'^\S+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9._-]+$') -link_target_attribute_re = re.compile(r'(<a [^>]*?)target=[^\s>]+') -html_gunk_re = re.compile(r'(?:<br clear="all">|<i><\/i>|<b><\/b>|<em><\/em>|<strong><\/strong>|<\/?smallcaps>|<\/?uppercase>)', re.IGNORECASE) -hard_coded_bullets_re = re.compile(r'((?:<p>(?:%s).*?[a-zA-Z].*?</p>\s*)+)' % '|'.join([re.escape(x) for x in DOTS]), re.DOTALL) -trailing_empty_content_re = re.compile(r'(?:<p>(?: |\s|<br \/>)*?</p>\s*)+\Z') - -  # And the template tags themselves...  @register.simple_tag @@ -195,15 +179,25 @@ def add_class(value, css_class):      return value +# Bunch of stuff cloned from urlize +TRAILING_PUNCTUATION = ['.', ',', ':', ';', '.)'] +WRAPPING_PUNCTUATION = [('(', ')'), ('<', '>'), ('[', ']'), ('<', '>'), +                        ('"', '"'), ("'", "'")] +word_split_re = re.compile(r'(\s+)') +simple_url_re = re.compile(r'^https?://\w', re.IGNORECASE) +simple_url_2_re = re.compile(r'^www\.|^(?!http)\w[^@]+\.(com|edu|gov|int|mil|net|org)$', re.IGNORECASE) +simple_email_re = re.compile(r'^\S+@\S+\.\S+$') + +  @register.filter  def urlize_quoted_links(text, trim_url_limit=None, nofollow=True, autoescape=True):      """      Converts any URLs in text into clickable links. -    Works on http://, https://, www. links and links ending in .org, .net or -    .com. Links can have trailing punctuation (periods, commas, close-parens) -    and leading punctuation (opening parens) and it'll still do the right -    thing. +    Works on http://, https://, www. links, and also on links ending in one of +    the original seven gTLDs (.com, .edu, .gov, .int, .mil, .net, and .org). +    Links can have trailing punctuation (periods, commas, close-parens) and +    leading punctuation (opening parens) and it'll still do the right thing.      If trim_url_limit is not None, the URLs in link text longer than this limit      will truncated to trim_url_limit-3 characters and appended with an elipsis. @@ -216,24 +210,41 @@ def urlize_quoted_links(text, trim_url_limit=None, nofollow=True, autoescape=Tru      trim_url = lambda x, limit=trim_url_limit: limit is not None and (len(x) > limit and ('%s...' % x[:max(0, limit - 3)])) or x      safe_input = isinstance(text, SafeData)      words = word_split_re.split(force_text(text)) -    nofollow_attr = nofollow and ' rel="nofollow"' or ''      for i, word in enumerate(words):          match = None          if '.' in word or '@' in word or ':' in word: -            match = punctuation_re.match(word) -        if match: -            lead, middle, trail = match.groups() +            # Deal with punctuation. +            lead, middle, trail = '', word, '' +            for punctuation in TRAILING_PUNCTUATION: +                if middle.endswith(punctuation): +                    middle = middle[:-len(punctuation)] +                    trail = punctuation + trail +            for opening, closing in WRAPPING_PUNCTUATION: +                if middle.startswith(opening): +                    middle = middle[len(opening):] +                    lead = lead + opening +                # Keep parentheses at the end only if they're balanced. +                if (middle.endswith(closing) +                    and middle.count(closing) == middle.count(opening) + 1): +                    middle = middle[:-len(closing)] +                    trail = closing + trail +              # Make URL we want to point to.              url = None -            if middle.startswith('http://') or middle.startswith('https://'): -                url = middle -            elif middle.startswith('www.') or ('@' not in middle and \ -                    middle and middle[0] in string.ascii_letters + string.digits and \ -                    (middle.endswith('.org') or middle.endswith('.net') or middle.endswith('.com'))): -                url = 'http://%s' % middle -            elif '@' in middle and not ':' in middle and simple_email_re.match(middle): -                url = 'mailto:%s' % middle +            nofollow_attr = ' rel="nofollow"' if nofollow else '' +            if simple_url_re.match(middle): +                url = smart_urlquote(middle) +            elif simple_url_2_re.match(middle): +                url = smart_urlquote('http://%s' % middle) +            elif not ':' in middle and simple_email_re.match(middle): +                local, domain = middle.rsplit('@', 1) +                try: +                    domain = domain.encode('idna').decode('ascii') +                except UnicodeError: +                    continue +                url = 'mailto:%s@%s' % (local, domain)                  nofollow_attr = '' +              # Make link.              if url:                  trimmed = trim_url(middle) @@ -251,4 +262,4 @@ def urlize_quoted_links(text, trim_url_limit=None, nofollow=True, autoescape=Tru              words[i] = mark_safe(word)          elif autoescape:              words[i] = escape(word) -    return mark_safe(''.join(words)) +    return ''.join(words)  | 
