"""
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])