""" A Template subclass that html-escapes all strings passed from the context, except when they are of class HTMLEscapedString """ # FIXME: Missing: A template loader for this ... from django.core.template import Template, Lexer, DebugLexer, Parser, DebugParser, VariableNode, DebugVariableNode, StringOrigin from django.utils.html import escape, linebreaks from django.conf.settings import DEFAULT_CHARSET, TEMPLATE_DEBUG from django.core.template.loader import find_template_source class HTMLTemplate (Template): def __init__(self, template_string, origin=None): "Compilation stage" if TEMPLATE_DEBUG and origin == None: origin = StringOrigin(template_string) # Could do some crazy stack-frame stuff to record where this string # came from... self.nodelist = html_compile_string(template_string, origin) class HTMLParser(Parser): def create_variable_node(self, filter_expression): return HTMLVariableNode(filter_expression) class DebugHTMLParser(DebugParser): def create_variable_node(self, contents): return DebugHTMLVariableNode(contents) class HTMLVariableNode(VariableNode): def encode_output(self, output): if isinstance(output, HTMLEscapedString): return output.encode(DEFAULT_CHARSET) else: return linebreaks(escape(super(HTMLVariableNode).encode_output(self, output))) class DebugHTMLVariableNode(DebugVariableNode): def encode_output(self, output): if isinstance(output, HTMLEscapedString): return output.encode(DEFAULT_CHARSET) else: return linebreaks(escape(DebugVariableNode.encode_output(self, output))) class HTMLEscapedString (unicode): """Same as unicode, but HTMLVariableNode does not html-escape instants of HTMLEscapedString """ pass if TEMPLATE_DEBUG: lexer_factory = DebugLexer parser_factory = DebugHTMLParser else: lexer_factory = Lexer parser_factory = HTMLParser def html_compile_string(template_string, origin): "Compiles template_string into NodeList ready for rendering" lexer = lexer_factory(template_string, origin) parser = parser_factory(lexer.tokenize()) return parser.parse() def get_template_from_string(source, origin=None): return HTMLTemplate(source, origin) def get_template(template_name): return get_template_from_string(*find_template_source(template_name)) if __name__=='__main__': from django.core.template import Context TEMPLATE_DEBUG=True t = HTMLTemplate("""" Dies ist ein Test. {{ s1 }} {{ s2 }} """) c = Context({'s1': u'blabla\n\nboblo&auch', 's2': HTMLEscapedString(u'nochwas\n\nblo& test')}) try: print t.render(c) except: import pdb, sys pdb.post_mortem(sys.exc_info()[2])