mozilla / nunjucks

A powerful templating engine with inheritance, asynchronous control, and more (jinja2 inspired)
https://mozilla.github.io/nunjucks/
BSD 2-Clause "Simplified" License
8.52k stars 637 forks source link

super() not working for nested blocks #928

Open legutierr opened 7 years ago

legutierr commented 7 years ago

Suppose we have a set of three templates, a child, a parent and a grandparent:

 var grandparent = "{% block container %}\n" +
   "block container grandparent\n" +
   "{% block outer %}\n" +
   "block outer grandparent\n" +
   "{% block inner1 %}\n" +
   "block inner grandparent\n" +
   "{% endblock %}\n" +
   "{% endblock %}\n" +
   "{% endblock %}\n";

var parent = "{% extends grandparent %}\n" +
   "{% block outer %}\n" +
   "block outer parent\n" +
   "{% block inner2 %}\n" +
   "block inner2 parent\n" +
   "{% endblock %}\n" +
   "{% endblock %}\n";

var child = "{% extends parent %}\n" +
   "{% block outer %}\n" +
   "block outer child\n" +
   "{% block inner1 %}\n" +
   "{{ super() }}\n" +
   "{% endblock %}\n" +
   "{% endblock %}\n";

When we render them...

var n = require('nunjucks');
var value = (new n.Template(child)).render({'parent':(new n.Template(parent)), 
                                            'grandparent':(new n.Template(grandparent))});

...we should expect to see the contents of the grandparent's inner1 block print out. But we don't; super() doesn't do anything:

> console.log(value);

block container grandparent

block outer child

This is inconsistent with the behavior of both Jinja2 and Twig, which are in agreement as to behavior here. For instance:

grandparent = """{% block container %}
block container grandparent
{% block outer %}
block outer grandparent
{% block inner1 %}
block inner grandparent
{% endblock %}
{% endblock %}
{% endblock %}"""

parent = """{% extends grandparent %}
{% block outer %}
block outer parent
{% block inner2 %}
block inner2 parent
{% endblock %}
{% endblock %}"""

child = """{% extends parent %}
{% block outer %}
block outer child
{% block inner1 %}
{{ super() }}
{% endblock %}
{% endblock %}"""

import jinja2 as j
value = j.Template(child).render({'parent':j.Template(parent), 
                                  'grandparent':j.Template(grandparent)})

Here, super() does actually print the contents of the grandparent's inner1 block:

>>> print value

block container grandparent

block outer child

base inner grandparent

Again, Twig's behavior is consistent with that of Jinja2, but for brevity's sake I will avoid demonstrating it here.

hugodes commented 7 years ago

I've noticed the same behavior on my end, jinja2 and twig both support the super() method on nested blocks.

eah13 commented 7 years ago

+1

The super'd block apparently doesn't need to be in the grandparent as I'm getting this behavior when trying to super a parent block from child in a three deep nesting of templates on 1.3.4.

To state this in terms of the example above, the following code in child would return nothing:

{% block inner2 %}
{{ super() }}
{% endblock %}