pallets / jinja

A very fast and expressive template engine.
https://jinja.palletsprojects.com
BSD 3-Clause "New" or "Revised" License
10.23k stars 1.6k forks source link

Autoescape does not work well across blocks/inheritance #1898

Open ThiefMaster opened 10 months ago

ThiefMaster commented 10 months ago

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