def visit_Filter(self, node, frame, initial=None):
self.write('f_%s(' % node.name)
- if initial is not None:
+ func = self.environment.filters.get(node.name)
+ if getattr(func, 'contextfilter', False):
+ self.write('context, ')
+ if isinstance(node.node, nodes.Filter):
+ self.visit_Filter(node.node, frame, initial)
+ elif node.node is None:
self.write(initial)
else:
- func = self.environment.filters.get(node.name)
- if getattr(func, 'contextfilter', False):
- self.write('context, ')
self.visit(node.node, frame)
self.signature(node, frame)
self.write(')')
except ImportError:
itemgetter = lambda a: lambda b: b[a]
from urllib import urlencode, quote
-from jinja2.utils import escape, pformat
-from jinja2.nodes import Undefined
+from jinja2.utils import escape, pformat, urlize
+from jinja2.runtime import Undefined
return env.undefined_singleton
-def do_urlencode(value):
- """
- urlencode a string or directory.
-
- .. sourcecode:: jinja
-
- {{ {'foo': 'bar', 'blub': 'blah'}|urlencode }}
- -> foo=bar&blub=blah
-
- {{ 'Hello World' }}
- -> Hello%20World
- """
- if isinstance(value, dict):
- tmp = {}
- for key, value in value.iteritems():
- # XXX env.charset?
- key = unicode(key).encode(env.charset)
- value = unicode(value).encode(env.charset)
- tmp[key] = value
- return urlencode(tmp)
- else:
- # XXX: env.charset?
- return quote(unicode(value).encode(env.charset))
-
-
def do_jsonencode(value):
"""
JSON dump a variable. just works if simplejson is installed.
'first': do_first,
'last': do_last,
'random': do_random,
- 'urlencode': do_urlencode,
'jsonencode': do_jsonencode,
'filesizeformat': do_filesizeformat,
'pprint': do_pprint,
:copyright: 2008 by Armin Ronacher.
:license: BSD, see LICENSE for more details.
"""
+import re
+import string
def escape(obj, attribute=False):
except ImportError:
from pprint import pformat
return pformat(obj)
+
+
+_word_split_re = re.compile(r'(\s+)')
+
+_punctuation_re = re.compile(
+ '^(?P<lead>(?:%s)*)(?P<middle>.*?)(?P<trail>(?:%s)*)$' % (
+ '|'.join([re.escape(p) for p in ('(', '<', '<')]),
+ '|'.join([re.escape(p) for p in ('.', ',', ')', '>', '\n', '>')])
+ )
+)
+
+_simple_email_re = re.compile(r'^\S+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9._-]+$')
+
+
+def urlize(text, trim_url_limit=None, nofollow=False):
+ """
+ Converts any URLs in text into clickable links. Works on http://,
+ https:// and www. links. 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 will be limited
+ to trim_url_limit characters.
+
+ If nofollow is True, the URLs in link text will get a rel="nofollow"
+ attribute.
+ """
+ trim_url = lambda x, limit=trim_url_limit: limit is not None \
+ and (x[:limit] + (len(x) >=limit and '...'
+ or '')) or x
+ words = _word_split_re.split(text)
+ nofollow_attr = nofollow and ' rel="nofollow"' or ''
+ for i, word in enumerate(words):
+ match = _punctuation_re.match(word)
+ if match:
+ lead, middle, trail = match.groups()
+ if middle.startswith('www.') or (
+ '@' not in middle and
+ not middle.startswith('http://') and
+ len(middle) > 0 and
+ middle[0] in string.letters + string.digits and (
+ middle.endswith('.org') or
+ middle.endswith('.net') or
+ middle.endswith('.com')
+ )):
+ middle = '<a href="http://%s"%s>%s</a>' % (middle,
+ nofollow_attr, trim_url(middle))
+ if middle.startswith('http://') or \
+ middle.startswith('https://'):
+ middle = '<a href="%s"%s>%s</a>' % (middle,
+ nofollow_attr, trim_url(middle))
+ if '@' in middle and not middle.startswith('www.') and \
+ not ':' in middle and _simple_email_re.match(middle):
+ middle = '<a href="mailto:%s">%s</a>' % (middle, middle)
+ if lead + middle + trail != word:
+ words[i] = lead + middle + trail
+ return u''.join(words)
{{ data|truncate(15, false, ">>>") }}|\
{{ smalldata|truncate(15) }}'''
UPPER = '''{{ "foo"|upper }}'''
-URLENCODE = '''{{ "f#b"|urlencode }}'''
URLIZE = '''{{ "foo http://www.example.com/ bar"|urlize }}'''
WORDCOUNT = '''{{ "foo bar baz"|wordcount }}'''
BLOCK = '''{% filter lower|escape %}<HEHE>{% endfilter %}'''
def test_string(env):
tmpl = env.from_string(STRING)
- assert tmpl.render(foo=range(10)) == str(range(10))
+ assert tmpl.render(foo=range(10)) == unicode(xrange(10))
def test_title(env):
assert tmpl.render() == 'FOO'
-def test_urlencode(env):
- tmpl = env.from_string(URLENCODE)
- assert tmpl.render() == 'f%23b'
-
-
def test_urlize(env):
tmpl = env.from_string(URLIZE)
assert tmpl.render() == 'foo <a href="http://www.example.com/">'\