def extends_macro(parser, expression): """Macro that implements an inherited child template.""" # Parse the rest of the template. nodes = parser.parse_all_nodes() # Go through the nodes, looking for all block tags. block_nodes = parser.meta.get("__blocks__") or parser.meta.setdefault("__blocks__", {}) return partial(extends_node, expression_evaluator(expression), block_nodes)
def parse_template_chunk(self, end_chunk_handler): """ Parses as many nodes as possible until an unknown block is reached. Returns the result of the end_chunk_handler. The chunk is ended when there is no more template to parse, or an unknown macro is encountered. Once this occurs, the end_chunk_handler is called with macro_name and nodes as positional arguments. The end_chunk handler must then process the nodes and return a result. """ nodes = [] for lineno, token_type, token_contents in self.tokens: try: if token_type == "STRING": node = partial(string_node, token_contents) elif token_type == "EXPRESSION": node = partial(expression_node, expression_evaluator(token_contents)) elif token_type == "MACRO": # Process macros. node = None for macro in self.macros: node = macro(self, token_contents) if node: break if not node: return end_chunk_handler(token_contents, nodes) else: assert False, "{!r} is not a valid token type.".format( token_type) # Set the node line number. nodes.append((lineno, node)) except TemplateCompileError: raise except Exception as ex: raise TemplateCompileError(str(ex), self.name, lineno) from ex # No unknown macro. return end_chunk_handler(None, nodes)
def if_macro(parser, expression): """A macro that implements an 'if' expression.""" clauses = [] else_tag = False else_block = None while True: match, block = parser.parse_block("if", "endif", RE_IF_CLAUSE) if else_tag: else_block = block else: clauses.append((expression_evaluator(expression), block)) elif_flag, elif_expression, else_flag, endif_flag = match.groups() if elif_flag: if else_tag: raise SyntaxError("{{% elif %}} tag cannot come after {{% else %}}.") expression = elif_expression elif else_flag: if else_tag: raise SyntaxError("Only one {{% else %}} tag is allowed per {{% if %}} macro.") else_tag = True elif endif_flag: break return partial(if_node, clauses, else_block)
def parse_template_chunk(self, end_chunk_handler): """ Parses as many nodes as possible until an unknown block is reached. Returns the result of the end_chunk_handler. The chunk is ended when there is no more template to parse, or an unknown macro is encountered. Once this occurs, the end_chunk_handler is called with macro_name and nodes as positional arguments. The end_chunk handler must then process the nodes and return a result. """ nodes = [] for lineno, token_type, token_contents in self.tokens: try: if token_type == "STRING": node = partial(string_node, token_contents) elif token_type == "EXPRESSION": node = partial(expression_node, expression_evaluator(token_contents)) elif token_type == "MACRO": # Process macros. node = None for macro in self.macros: node = macro(self, token_contents) if node: break if not node: return end_chunk_handler(token_contents, nodes) else: assert False, "{!r} is not a valid token type.".format(token_type) # Set the node line number. nodes.append((lineno, node)) except TemplateCompileError: raise except Exception as ex: raise TemplateCompileError(str(ex), self.name, lineno) from ex # No unknown macro. return end_chunk_handler(None, nodes)
def print_macro(parser, expression): """Macro that allows an expression to be rendered without autoescaping.""" return partial(print_node, expression_evaluator(expression))
def set_macro(parser, expression, name): """Macro that allows setting of a value in the context.""" return partial(set_node, expression_evaluator(expression), name_setter(name))
def include_macro(parser, expression): """Macro that implements an 'include' expression.""" return partial(include_node, expression_evaluator(expression))
def for_macro(parser, name, expression): """A macro that implements a 'for' loop.""" match, block = parser.parse_block("for", "endfor", RE_ENDFOR) return partial(for_node, name_setter(name), expression_evaluator(expression), block)