Fixed #11911 -- Made the urlize filter smarter with closing punctuation.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@17362 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
78c92c4167
commit
15d10a5210
|
@ -11,8 +11,8 @@ from django.utils.functional import allow_lazy
|
|||
from django.utils.text import normalize_newlines
|
||||
|
||||
# Configuration for urlize() function.
|
||||
LEADING_PUNCTUATION = ['(', '<', '<']
|
||||
TRAILING_PUNCTUATION = ['.', ',', ')', '>', '\n', '>']
|
||||
TRAILING_PUNCTUATION = ['.', ',', ':', ';']
|
||||
WRAPPING_PUNCTUATION = [('(', ')'), ('<', '>'), ('<', '>')]
|
||||
|
||||
# List of possible strings used for bullets in bulleted lists.
|
||||
DOTS = [u'·', u'*', u'\u2022', u'•', u'•', u'•']
|
||||
|
@ -20,9 +20,6 @@ DOTS = [u'·', u'*', u'\u2022', u'•', u'•', u'•']
|
|||
unencoded_ampersands_re = re.compile(r'&(?!(\w+|#\d+);)')
|
||||
unquoted_percents_re = re.compile(r'%(?![0-9A-Fa-f]{2})')
|
||||
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_url_re = re.compile(r'^https?://\w')
|
||||
simple_url_2_re = re.compile(r'^www\.|^(?!http)\w[^@]+\.(com|edu|gov|int|mil|net|org|[a-z]{2})$')
|
||||
simple_email_re = re.compile(r'^\S+@\S+\.\S+$')
|
||||
|
@ -147,9 +144,22 @@ def urlize(text, trim_url_limit=None, nofollow=False, autoescape=False):
|
|||
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
|
||||
nofollow_attr = ' rel="nofollow"' if nofollow else ''
|
||||
|
@ -162,6 +172,7 @@ def urlize(text, trim_url_limit=None, nofollow=False, autoescape=False):
|
|||
domain = domain.encode('idna')
|
||||
url = 'mailto:%s@%s' % (local, domain)
|
||||
nofollow_attr = ''
|
||||
|
||||
# Make link.
|
||||
if url:
|
||||
trimmed = trim_url(middle)
|
||||
|
|
|
@ -253,6 +253,14 @@ class DefaultFiltersTests(TestCase):
|
|||
u'<a href="http://en.wikipedia.org/wiki/Caf%C3%A9" rel="nofollow">'
|
||||
u'http://en.wikipedia.org/wiki/Café</a>')
|
||||
|
||||
# Check urlize keeps balanced parentheses - see #11911
|
||||
self.assertEqual(urlize('http://en.wikipedia.org/wiki/Django_(web_framework)'),
|
||||
u'<a href="http://en.wikipedia.org/wiki/Django_(web_framework)" rel="nofollow">'
|
||||
u'http://en.wikipedia.org/wiki/Django_(web_framework)</a>')
|
||||
self.assertEqual(urlize('(see http://en.wikipedia.org/wiki/Django_(web_framework))'),
|
||||
u'(see <a href="http://en.wikipedia.org/wiki/Django_(web_framework)" rel="nofollow">'
|
||||
u'http://en.wikipedia.org/wiki/Django_(web_framework)</a>)')
|
||||
|
||||
# Check urlize adds nofollow properly - see #12183
|
||||
self.assertEqual(urlize('foo@bar.com or www.bar.com'),
|
||||
u'<a href="mailto:foo@bar.com">foo@bar.com</a> or '
|
||||
|
|
Loading…
Reference in New Issue