jinja icon indicating copy to clipboard operation
jinja copied to clipboard

Autoescape does not work well across blocks/inheritance

Open ThiefMaster opened this issue 2 years ago • 0 comments

Description

I have a base template that uses {% autoescape false %} around a block because the contents of that particular block are used in a plaintext context that does not need escaping, while the rest of the template does.

However, when override that block in the main template, autoescaping still happens - see test1 in the output below.

test2 is completely weird and makes no sense at all - wrapping the block in autoescape should have no effect whatsoever (since nothing outside of blocks should be taken into account in a template that uses {% extends %}.

test3 has the desired result, but at the cost of having to duplicate the autoescape false block in each child template, which is exactly what I'm trying to avoid.

Example

import textwrap

from jinja2 import DictLoader, Environment, select_autoescape

TEMPLATES = {
    'base.html': textwrap.dedent('''
        Subject: {% autoescape false %}{% block subject %}{% endblock %}{% endautoescape %}
        Body: {% block body %}{% endblock %}
    ''').strip(),
    'test1.html': textwrap.dedent('''
        {% extends 'base.html' %}
        {% block subject %}{{ text }}{% endblock %}
        {% block body %}{{ text }}{% endblock %}
    ''').strip(),
    'test2.html': textwrap.dedent('''
        {% extends 'base.html' %}
        {% autoescape false -%}
            {% block subject %}{{ text }}{% endblock %}
        {%- endautoescape %}
        {% block body %}{{ text }}{% endblock %}
    ''').strip(),
    'test3.html': textwrap.dedent('''
        {% extends 'base.html' %}
        {% block subject %}
            {%- autoescape false %}{{ text }}{% endautoescape -%}
        {% endblock %}
        {% block body %}{{ text }}{% endblock %}
    ''').strip(),
}

TEXT = "hel'lo"

env = Environment(loader=DictLoader(TEMPLATES), autoescape=select_autoescape())
print('test1')
print(env.get_template('test1.html').render(text=TEXT))
print()
print('test2')
print(env.get_template('test2.html').render(text=TEXT))
print()
print('test3')
print(env.get_template('test3.html').render(text=TEXT))

Output

test1
Subject: hel'lo
Body: hel'lo

test2
hel'loSubject: hel'lo
Body: hel'lo

test3
Subject: hel'lo
Body: hel'lo

Environment

  • Python version: 3.11.6 + 3.12.0 (+ probably all other versions)
  • Jinja version: 3.1.2 + ... + 2.7 (did not test anything older than that)

ThiefMaster avatar Oct 13 '23 11:10 ThiefMaster