Compile subsection of Jinja2 AST
Can one compile or revert a portion of the Jinja2 AST?
For example, is it possible to call a function or method from jinja2.environment
or jinja2.compiler.generate
开发者_高级运维 or some equivalent on a list of nodes extracted from within a template?
For example, given a template y.html
:
avant-tag
{% xyz %}
tag content {{ 3 + 5 }}
{% endxyz %}
apres-tag
and an extension y.py
:
# -*- coding: utf-8 -*-
from jinja2 import nodes, Environment, FileSystemLoader
from jinja2.ext import Extension
class YExtension(Extension):
tags = set(['y'])
def __init__(self, environment):
super(YExtension, self).__init__(environment)
def parse(self, parser):
tag = parser.stream.next()
body = parser.parse_statements(['name:endy'], drop_needle=True)
return nodes.Const("<!-- slurping: %s -->" % str(body))
env = Environment(
loader = FileSystemLoader('.'),
extensions = [YExtension],
)
print env.get_template('x.html').render()
Running python y.py
results in the expected output of:
avant-tag
<!-- slurping: [Output(nodes=[TemplateData(data=u'\n tag-content '),
Add(left=Const(value=3), right=Const(value=5)),
TemplateData(data=u'\n ')])] -->
sous-tag
In the parse
method, how can one either:
- compile
body
to unicode (i.e.tag-content 8
); or, alternatively - revert
body
to its original source (i.e.tag-content {{ 3 + 5 }}
).
As a matter of background, this question relates to two prior questions:
- Jinja2 compile extension after includes; and
- Insert javascript at top of including file in Jinja 2
Thank you for reading.
Brian
Compiling to unicode is not yet possible in the parse()
method since you don't have the context available at that point. You can hack around it ofcourse but it would probably not be the best way to go.
Note that the parse()
step is normally only executed once on a html file, after that it will use the parsed bytecode to render the template. The results of the parse step can be rendered given an environment.
You simply don't have the context available there, and getting the context in there... quite difficult ;)
To get the original source however... not much easier without hacking, but the hacking isn't too bad ;)
class YExtension(Extension):
tags = set(['y'])
def preprocess(self, source, name, filename=None):
# insert some code here that replaces '{% xyz %}foo bar{% endxyz %}'
# with something like: '{% xyz %}foo bar{% raw %}foo bar{% endraw %}{% endxyz %}'
return source
After that you can read the text as the value
from the {% raw %}
node. Be sure to trash it after that or it will show in your template.
精彩评论