--- /dev/null
+===================
+TODO List for Jinja
+===================
+
+- Requirements in Jinja (blocks and set directives) outside of renderable
+ blocks should become part of the module not the generate function.
+
+- Improve the context lookup (maybe with an optional C extension)
--- /dev/null
+=====================
+Framework Integration
+=====================
+
+Jinja registers itself in the baker template plugin system. If your framework
+supports baker (currently `TurboGears`_ and `pylons`_) you can add it very
+easy.
+
+Pylons
+------
+
+Edit ``yourproject/config/middleware.py`` and add the following lines to
+`config.init_app...`:
+
+.. sourcecode:: python
+
+ from jinja import Environment, FileSystemLoader
+
+ config.add_template_engine('jinja', {
+ 'jinja.environment': Environment(loader=FileSystemLoader('path/to/templates'))
+ })
+
+To make Jinja the default template engine change the `init_app` call to
+something like this:
+
+.. sourcecode:: python
+
+ config.init_app(global_conf, app_conf, package='yourproject',
+ template_engine='jinja')
+
+
+.. _TurboGears: http://www.turbogears.org/
+.. _pylons: http://www.pylonshq.com/
- `Translators <translators.txt>`_
+ - `Framework Integration <frameworks.txt>`_
+
- Template Designer Documentation:
- `Syntax Reference <designerdoc.txt>`_
return True
eos = property(lambda x: not x.__nonzero__(), doc=__nonzero__.__doc__)
-
+
def next(self):
"""Return the next token from the stream."""
if self._pushed:
except StopIteration:
raise IndexError('end of stream reached')
+ def drop_until(self, test, drop_needle=False):
+ """Fetch tokens until a function matches and drop all
+ tokens."""
+ for token in self.fetch_until(test, drop_needle):
+ pass
+
def push(self, lineno, token, data):
"""Push an yielded token back to the stream."""
self._pushed.append((lineno, token, data))
-> 123
"""
def wrapped(env, context, value):
- d = env.to_unicode(d)
- return d.join([env.to_unicode(x) for x in value])
+ return env.to_unicode(d).join([env.to_unicode(x) for x in value])
return wrapped
def wrapped(env, context, value):
try:
if type(value) in (int, float, long):
- return len(str(var))
- return len(var)
+ return len(str(value))
+ return len(value)
except TypeError:
return 0
return wrapped
'default': do_default,
'join': do_join,
'count': do_count,
+ 'length': do_count,
'reverse': do_reverse,
'center': do_center,
'title': do_title,
# callback functions for the subparse method
end_of_block = lambda p, t, d: t == 'block_end'
end_of_variable = lambda p, t, d: t == 'variable_end'
+end_of_comment = lambda p, t, d: t == 'comment_end'
switch_for = lambda p, t, d: t == 'name' and d in ('else', 'endfor')
end_of_for = lambda p, t, d: t == 'name' and d == 'endfor'
switch_if = lambda p, t, d: t == 'name' and d in ('else', 'elif', 'endif')
while True:
lineno, token, data = self.tokenstream.next()
+ # comments
+ if token == 'comment_begin':
+ self.tokenstream.drop_until(end_of_comment, True)
# nested variables
- if token == 'variable_begin':
+ elif token == 'variable_begin':
_, variable_token, variable_name = self.tokenstream.next()
if variable_token != 'name' or variable_name not in replacements:
raise TemplateSyntaxError('unregistered translation '
lineno = self.tokenstream.last[0]
result = nodes.NodeList(lineno)
for lineno, token, data in self.tokenstream:
+ # comments
+ if token == 'comment_begin':
+ self.tokenstream.drop_until(end_of_comment, True)
+
# this token marks the begin or a variable section.
# parse everything till the end of it.
- if token == 'variable_begin':
+ elif token == 'variable_begin':
gen = self.tokenstream.fetch_until(end_of_variable, True)
result.append(self.directives['print'](lineno, gen))
write('def macro(*args):')
self.indention += 1
+ write('context.push()')
write('%s = (args + %s[len(args):])' % (_to_tuple(args), _to_tuple(defaults)))
write('macrobuffer = []')
write('write = macrobuffer.append')
buf.append(self.handle_node(node.body))
+ write('context.pop()')
write('return u\'\'.join(macrobuffer)')
self.indention -= 1
buf.append(self.indent('context[%r] = macro' % node.name))