Skip to content

Commit

Permalink
Support filters in set block
Browse files Browse the repository at this point in the history
- e.g {% set foo | trim %}...{% endset %}
- closes #486
  • Loading branch information
ThiefMaster committed Jan 7, 2017
1 parent bbe0a41 commit 8158949
Show file tree
Hide file tree
Showing 6 changed files with 34 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGES
Expand Up @@ -43,6 +43,7 @@ Version 2.9
- The `with` and `autoescape` tags are now built-in.
- Added the new `select_autoescape` function which helps configuring better
autoescaping easier.
- Added filter support to the block ``set`` tag.

Version 2.8.2
-------------
Expand Down
11 changes: 11 additions & 0 deletions docs/templates.rst
Expand Up @@ -865,6 +865,17 @@ Example::

The `navigation` variable then contains the navigation HTML source.

.. versionchanged:: 2.9

Starting with Jinja 2.9, the block assignment supports filters.

Example::

{% set reply | wordwrap %}
You wrote:
{{ message }}
{% endset %}


.. _extends:

Expand Down
7 changes: 6 additions & 1 deletion jinja2/compiler.py
Expand Up @@ -1314,7 +1314,12 @@ def visit_AssignBlock(self, node, frame):
self.newline(node)
self.visit(node.target, frame)
self.write(' = (Markup if context.eval_ctx.autoescape '
'else identity)(concat(%s))' % block_frame.buffer)
'else identity)(')
if node.filter is not None:
self.visit_Filter(node.filter, block_frame)
else:
self.write('concat(%s)' % block_frame.buffer)
self.write(')')
self.pop_assign_tracking(frame)
self.leave_frame(block_frame)

Expand Down
2 changes: 1 addition & 1 deletion jinja2/nodes.py
Expand Up @@ -378,7 +378,7 @@ class Assign(Stmt):

class AssignBlock(Stmt):
"""Assigns a block to a target."""
fields = ('target', 'body')
fields = ('target', 'filter', 'body')


class Expr(Node):
Expand Down
3 changes: 2 additions & 1 deletion jinja2/parser.py
Expand Up @@ -180,9 +180,10 @@ def parse_set(self):
if self.stream.skip_if('assign'):
expr = self.parse_tuple()
return nodes.Assign(target, expr, lineno=lineno)
filter_node = self.parse_filter(None)
body = self.parse_statements(('name:endset',),
drop_needle=True)
return nodes.AssignBlock(target, body, lineno=lineno)
return nodes.AssignBlock(target, filter_node, body, lineno=lineno)

def parse_for(self):
"""Parse a for loop."""
Expand Down
13 changes: 13 additions & 0 deletions tests/test_core_tags.py
Expand Up @@ -354,3 +354,16 @@ def test_block_escaping(self):
tmpl = env.from_string('{% set foo %}<em>{{ test }}</em>'
'{% endset %}foo: {{ foo }}')
assert tmpl.render(test='<unsafe>') == 'foo: <em>&lt;unsafe&gt;</em>'

def test_block_escaping_filtered(self):
env = Environment(autoescape=True)
tmpl = env.from_string('{% set foo | trim %}<em>{{ test }}</em> '
'{% endset %}foo: {{ foo }}')
assert tmpl.render(test='<unsafe>') == 'foo: <em>&lt;unsafe&gt;</em>'

def test_block_filtered(self, env_trim):
tmpl = env_trim.from_string(
'{% set foo | trim | length | string %} 42 {% endset %}'
'{{ foo }}')
assert tmpl.render() == '2'
assert tmpl.module.foo == u'2'

0 comments on commit 8158949

Please sign in to comment.