def visit_Template(self, node, frame=None): eval_ctx = EvalContext(self.environment, self.name) # do we have an extends tag at all? If not, we can save some # overhead by just not processing any inheritance code. have_extends = node.find(nodes.Extends) is not None # find all blocks for block in node.find_all(nodes.Block): if block.name in self.blocks: self.fail("block %r defined twice" % block.name, block.lineno) self.blocks[block.name] = block self.writeline("(function(){return {") self.writeline("renderFunc: function(env, context, stream) {") frame = Frame(eval_ctx) frame.inspect(node.body) frame.toplevel = frame.rootlevel = True frame.require_output_check = have_extends and not self.has_known_extends if have_extends: self.writeline("var parentTemplate = undefined;") if "self" in find_undeclared(node.body, ("self",)): frame.identifiers.add_special("self") self.writeline("var l_self = new Jinjs.TemplateReference(context);") self.pull_locals(frame) self.blockvisit(node.body, frame) # make sure that the parent root is called. if have_extends: if not self.has_known_extends: self.writeline("if (parentTemplate !== undefined) {") self.writeline("parentTemplate.renderFunc(env, context, stream);") if not self.has_known_extends: self.writeline("}") self.writeline("},") self.writeline("name: %s," % json.dumps(self.name)) self.writeline("blocks: {") # at this point we now have the blocks collected and can visit them too. for name, block in self.blocks.iteritems(): block_frame = Frame() block_frame.inspect(block.body) block_frame.block = name self.writeline("%s: function(env, context, stream) {" % name) undeclared = find_undeclared(block.body, ("self", "super")) if "self" in undeclared: block_frame.identifiers.add_special("self") self.writeline("var l_self = new Jinjs.TemplateReference(context);") if "super" in undeclared: block_frame.identifiers.add_special("super") self.writeline("var l_super = context.super(%r, " "block_%s)" % (name, name)) self.pull_locals(block_frame) self.blockvisit(block.body, block_frame) self.writeline("},") self.writeline("}};})()")
def visit_Template(self, node, frame=None): eval_ctx = EvalContext(self.environment, self.name) # find all blocks for block in node.find_all(nodes.Block): if block.name in self.blocks: self.fail('block %r defined twice' % block.name, block.lineno) self.blocks[block.name] = block for import_ in node.find_all(nodes.ImportedName): assert False, "imports not supported" self.safename = self.name.replace(".","_") self.writeline('var tpl_%s = new function()' % self.safename) self.indent() frame = Frame(eval_ctx) frame.inspect(node.body) frame.toplevel = frame.rootlevel = True frame.require_output_check = not self.has_known_extends self.buffer(frame) # at this point we now have the blocks collected and can visit them too. for name, block in self.blocks.iteritems(): block_frame = Frame(eval_ctx) block_frame.inspect(block.body) block_frame.block = name block_frame.buffer = frame.buffer self.writeline('var block_%s = function(context, %s)' % (name, frame.buffer), block, 1) self.indent() undeclared = find_undeclared(block.body, ('self', 'super')) if 'self' in undeclared: block_frame.identifiers.add_special('self') self.writeline('l_self = TemplateReference(context)') if 'super' in undeclared: block_frame.identifiers.add_special('super') self.writeline('l_super = context.super_block(block_%s)' % name) self.pull_locals(block_frame) self.pull_dependencies(block.body) self.blockvisit(block.body, block_frame) self.outdent() self.writeline('var blocks = {%s};' % ', '.join('%r: block_%s' % (x, x) for x in self.blocks), extra=1) self.writeline("var name = %r"% self.name) self.writeline('return') self.indent() self.writeline('name: name,') self.writeline('root: function(context)', extra=1) self.indent() self.writeline('if(context.blocks==undefined)') self.indent() self.writeline("context.blocks=blocks") self.outdent() self.clear_buffer(frame) self.writeline('var parent_template = null;') if 'self' in find_undeclared(node.body, ('self',)): frame.identifiers.add_special('self') self.writeline('l_self = context.call_blocks()') self.pull_locals(frame) self.pull_dependencies(node.body) self.blockvisit(node.body, frame) self.writeline("if(parent_template)") self.indent() self.writeline('return parent_template.root(context)') self.outdent() self.return_buffer_contents(frame) self.outdent() """ if not self.has_known_extends: self.indent() self.writeline('if parent_template is not None:') self.indent() """ self.write(',') self.writeline('blocks: blocks') self.outdent() self.outdent() self.writeline('if(typeof(environment)!="undefined")') self.indent() self.writeline('environment.tpl[%r] = tpl_%s' % (self.name, self.safename)) self.outdent()
def template_ast(self, node, frame=None): # pragma: no cover """ Shim for Jinja2's default ``Jinja``-sytnax-to-Python AST converter. Wraps template code in a module-level ``run`` function that binds it to an instance of :py:class:`jinja2.Environment`. :param node: Current AST node. :param frame: Current code frame. :return: ``None``. """ assert frame is None, "no root frame allowed" eval_ctx = EvalContext(self.environment, self.name) from jinja2.runtime import __all__ as exported self.writeline("# -*- coding: utf-8 -*-") self.writeline("") self.writeline("from __future__ import division") self.writeline("from jinja2.runtime import " + ", ".join(exported)) if not unoptimize_before_dead_code: self.writeline("dummy = lambda *x: None") # if we want a deferred initialization we cannot move the # environment into a local name envenv = not self.defer_init and ", environment=environment" or "" # do we have an extends tag at all? If not, we can save some # overhead by just not processing any inheritance code. have_extends = node.find(nodes.Extends) is not None # find all blocks for block in node.find_all(nodes.Block): if block.name in self.blocks: self.fail("block %r defined twice" % block.name, block.lineno) self.blocks[block.name] = block # find all imports and import them for import_ in node.find_all(nodes.ImportedName): if import_.importname not in self.import_aliases: imp = import_.importname self.import_aliases[imp] = alias = self.temporary_identifier() if "." in imp: module, obj = imp.rsplit(".", 1) self.writeline("from %s import %s as %s" % (module, obj, alias)) else: self.writeline("import %s as %s" % (imp, alias)) # add the load name self.writeline("name = %r" % self.name) # generate the deferred init wrapper self.writeline("def run(environment):", extra=1) self.indent() # generate the root render function. self.writeline("def root(context%s):" % envenv, extra=1) # process the root frame = Frame(eval_ctx) frame.inspect(node.body) frame.toplevel = frame.rootlevel = True frame.require_output_check = have_extends and not self.has_known_extends self.indent() if have_extends: self.writeline("parent_template = None") if "self" in find_undeclared(node.body, ("self",)): frame.identifiers.add_special("self") self.writeline("l_self = TemplateReference(context)") self.pull_locals(frame) self.pull_dependencies(node.body) self.blockvisit(node.body, frame) self.outdent() # make sure that the parent root is called. if have_extends: if not self.has_known_extends: self.indent() self.writeline("if parent_template is not None:") self.indent() self.writeline("for event in parent_template." "root_render_func(context):") self.indent() self.writeline("yield event") self.outdent(2 + (not self.has_known_extends)) # at this point we now have the blocks collected and can visit them too. for name, block in iteritems(self.blocks): block_frame = Frame(eval_ctx) block_frame.inspect(block.body) block_frame.block = name self.writeline("def block_%s(context%s):" % (name, envenv), block, 1) self.indent() undeclared = find_undeclared(block.body, ("self", "super")) if "self" in undeclared: block_frame.identifiers.add_special("self") self.writeline("l_self = TemplateReference(context)") if "super" in undeclared: block_frame.identifiers.add_special("super") self.writeline("l_super = context.super(%r, " "block_%s)" % (name, name)) self.pull_locals(block_frame) self.pull_dependencies(block.body) self.blockvisit(block.body, block_frame) self.outdent() self.writeline("blocks = {%s}" % ", ".join("%r: block_%s" % (x, x) for x in self.blocks), extra=1) # add a function that returns the debug info self.writeline("debug_info = %r" % "&".join("%s=%s" % x for x in self.debug_info)) self.writeline("return (root, blocks, debug_info)") self.outdent() self.writeline("")