Permalink
Browse files

autoescape no longer is a plain boolean value but can also be a function

to enable or disable autoescaping for certain filenames (or file
extensions for that matter)

--HG--
branch : trunk
  • Loading branch information...
1 parent cedb482 commit 1da23d19ec379321672a1aa93b8aab81fd9362de @mitsuhiko mitsuhiko committed Apr 5, 2010
Showing with 66 additions and 8 deletions.
  1. +32 −0 docs/api.rst
  2. +1 −1 jinja2/compiler.py
  3. +7 −1 jinja2/environment.py
  4. +5 −2 jinja2/nodes.py
  5. +3 −3 jinja2/runtime.py
  6. +18 −1 jinja2/testsuite/api.py
View
@@ -220,6 +220,38 @@ useful if you want to dig deeper into Jinja2 or :ref:`develop extensions
:members: disable_buffering, enable_buffering, dump
+Autoescaping
+------------
+
+.. versionadded:: 2.4
+
+As of Jinja 2.4 the preferred way to do autoescaping is to enable the
+:ref:`autoescape-extension` and to configure a sensible default for
+autoescaping. This makes it possible to enable and disable autoescaping
+on a per-template basis (HTML versus text for instance).
+
+Here a recommended setup that enables autoescaping for templates ending
+in ``'.html'``, ``'.htm'`` and ``'.xml'`` and disabling it by default
+for all other extensions::
+
+ def guess_autoescape(template_name):
+ if template_name is None or '.' not in template_name:
+ return False
+ ext = template_name.rsplit('.', 1)[1]
+ return ext in ('html', 'htm', 'xml')
+
+ env = Environment(autoescape=guess_autoescape,
+ loader=PackageLoader('mypackage'),
+ extensions=['jinja2.ext.autoescape'])
+
+When implementing a guessing autoescape function, make sure you also
+accept `None` as valid template name. This will be passed when generating
+templates from strings.
+
+Inside the templates the behaviour can be temporarily changed by using
+the `autoescape` block (see :ref:`autoescape-overrides`).
+
+
.. _identifier-naming:
Notes on Identifiers
View
@@ -761,7 +761,7 @@ def position(self, node):
def visit_Template(self, node, frame=None):
assert frame is None, 'no root frame allowed'
- eval_ctx = EvalContext(self.environment)
+ eval_ctx = EvalContext(self.environment, self.name)
from jinja2.runtime import __all__ as exported
self.writeline('from __future__ import division')
@@ -160,7 +160,13 @@ class Environment(object):
`autoescape`
If set to true the XML/HTML autoescaping feature is enabled by
default. For more details about auto escaping see
- :class:`~jinja2.utils.Markup`.
+ :class:`~jinja2.utils.Markup`. As of Jinja 2.4 this can also
+ be a callable that is passed the template name and has to
+ return `True` or `False` depending on autoescape should be
+ enabled by default.
+
+ .. versionchanged:: 2.4
+ `autoescape` can now be a function
`loader`
The template loader for this environment.
View
@@ -72,8 +72,11 @@ class EvalContext(object):
to it in extensions.
"""
- def __init__(self, environment):
- self.autoescape = environment.autoescape
+ def __init__(self, environment, template_name=None):
+ if callable(environment.autoescape):
+ self.autoescape = environment.autoescape(template_name)
+ else:
+ self.autoescape = environment.autoescape
self.volatile = False
def save(self):
View
@@ -77,7 +77,7 @@ def __init__(self, context):
def __getitem__(self, name):
blocks = self.__context.blocks[name]
- wrap = self.__context.environment.autoescape and \
+ wrap = self.__context.eval_ctx.autoescape and \
Markup or (lambda x: x)
return BlockReference(name, self.__context, blocks, 0)
@@ -114,7 +114,7 @@ def __init__(self, environment, parent, name, blocks):
self.parent = parent
self.vars = {}
self.environment = environment
- self.eval_ctx = EvalContext(self.environment)
+ self.eval_ctx = EvalContext(self.environment, name)
self.exported_vars = set()
self.name = name
@@ -257,7 +257,7 @@ def super(self):
@internalcode
def __call__(self):
rv = concat(self._stack[self._depth](self._context))
- if self._context.environment.autoescape:
+ if self._context.eval_ctx.autoescape:
rv = Markup(rv)
return rv
@@ -17,7 +17,7 @@
from jinja2 import Environment, Undefined, DebugUndefined, \
StrictUndefined, UndefinedError, Template, meta, \
- is_undefined, Template
+ is_undefined, Template, DictLoader
from jinja2.utils import Cycler
env = Environment()
@@ -76,6 +76,23 @@ def test_template_passthrough(self):
assert env.get_or_select_template([t]) is t
assert env.get_or_select_template(t) is t
+ def test_autoescape_autoselect(self):
+ def select_autoescape(name):
+ if name is None or '.' not in name:
+ return False
+ return name.endswith('.html')
+ env = Environment(autoescape=select_autoescape,
+ loader=DictLoader({
+ 'test.txt': '{{ foo }}',
+ 'test.html': '{{ foo }}'
+ }))
+ t = env.get_template('test.txt')
+ assert t.render(foo='<foo>') == '<foo>'
+ t = env.get_template('test.html')
+ assert t.render(foo='<foo>') == '&lt;foo&gt;'
+ t = env.from_string('{{ foo }}')
+ assert t.render(foo='<foo>') == '<foo>'
+
class MetaTestCase(JinjaTestCase):

0 comments on commit 1da23d1

Please sign in to comment.