Skip to content

Instantly share code, notes, and snippets.

@codysoyland
Created June 10, 2010 15:50
from django.template import Parser, Lexer, Token, Context, TextNode, TOKEN_BLOCK, TOKEN_COMMENT, TOKEN_TEXT, TOKEN_VAR
from django.conf import settings
LITERAL_DELIMITER = '8====D'
class LiteralNode(TextNode):
pass
def parse(parser):
depth = 0
while parser.tokens:
token = parser.next_token()
if token.token_type == TOKEN_BLOCK:
if token.contents == 'literal':
depth += 1
elif token.contents == 'endliteral':
depth -= 1
if depth < 0:
break
yield token
if not parser.tokens and depth >= 0:
parser.unclosed_block_tag(('endliteral',))
def do_literal(parser, token):
literal = ''.join({
TOKEN_BLOCK: '{%% %s %%}',
TOKEN_VAR: '{{ %s }}',
TOKEN_COMMENT: '{# %s #}',
TOKEN_TEXT: '%s',
}[token.token_type] % token.contents for token in parse(parser))
literal = '%s%s%s' % (LITERAL_DELIMITER, literal, LITERAL_DELIMITER)
return LiteralNode(literal)
def first_pass(data):
lexer = Lexer(data, None)
parser = Parser(lexer.tokenize())
parser.tags['literal'] = do_literal
context = Context({'a_var': 'foo!'})
nodes = parser.parse()
rendered = ''.join(node.render(context) for node in nodes)
return rendered
def second_pass(data):
bits = data.split(LITERAL_DELIMITER)
parser = Parser([])
context = Context({'a_var': 'foo!'})
for index, bit in enumerate(bits):
if index % 2:
parser.tokens += Lexer(bit, None).tokenize()
else:
parser.tokens.append(Token( TOKEN_TEXT, bit))
nodes = parser.parse()
rendered = ''.join(node.render(context) for node in nodes)
return rendered
if __name__ == '__main__':
data = """
before
{{ a_var }}
{% templatetag openblock %} scary UGC hack {% templatetag closeblock %}
{% literal %}
{% if 1 %}
this is literal
{# comment #}
{{ a_var|upper }}
{% endif %}
{% endliteral %}
between
{% literal %}
second literal bit
{{ a_var }}
{% endliteral %}
after
"""
settings.configure()
pass1 = first_pass(data)
pass2 = second_pass(pass1)
print '=======AFTER PASS1========'
print pass1
print '=======AFTER PASS2========'
print pass2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment