-
Notifications
You must be signed in to change notification settings - Fork 0
/
jsmetatemplate.py
118 lines (91 loc) · 3.54 KB
/
jsmetatemplate.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
from django import template
from django.template.loader_tags import do_include
import re
register = template.Library()
class JsTemplateBaseNode(template.Node):
"""
The base node for a javascript metatemplate
LEFT_PATTERN and RIGHT_PATTERN are used as a substitute delimiter
for templating languages (like moustache) that use '{{'
this node in instantiated with an inner_node, which comes from the
django builtin do_include function.
when this node is rendered, it renders the meta-template stored in
the inner_node, then replaces all instances of LEFT_PATTERN and RIGHT_PATTERN
with LEFT_TARGET and RIGHT_TARGET (by default '{{' and '}}' respectively)
it surrounds this rendered text by the result of the top() and bottom() methods,
allowing it to be inserted with the appropriate context (<script> tags and other
templating language specific things)
"""
LEFT_PATTERN = re.compile(r'{!')
RIGHT_PATTERN = re.compile(r'!}')
LEFT_TARGET = '{{'
RIGHT_TARGET = '}}'
def __init__(self, inner_node):
"""
Instantiated with a inner_node as an argument
This node comes from the from the do_include function
"""
self.inner_node = inner_node
## attempting to get the tmplate name
# depends whether it is an IncludeNode or ConstantIncludeNode
try:
self.template_name = inner_node.template_name
except AttributeError:
self.template_name = inner_node.template.name
def top(self):
"""
for subclasses - what comes before the rendered meta templates
defaults to ''
"""
return ''
def bottom(self):
"""
for subclasses - what comes after the rendered meta template
defaults to ''
"""
return ''
def render(self, context):
"""
renders the inner node (the included template)
then replaces the js delimiters with the actual delimiters
then returns top() + js_template + bottom()!
"""
js_template = self.inner_node.render(context)
left_replaced_js_template = self.LEFT_PATTERN.sub(self.LEFT_TARGET, js_template)
left_right_replaced_js_template = self.RIGHT_PATTERN.sub(self.RIGHT_TARGET, left_replaced_js_template)
return "%s\n%s\n%s" % (
self.top(),
left_right_replaced_js_template,
self.bottom(),
)
class IchTemplateNode(JsTemplateBaseNode):
"""
implements the wrapper for icanhaz
"""
def top(self):
return "<script type='text/html' id='%s'>" % self.template_name
def bottom(self):
return "</script>"
#########
# registering stuff
register_hash = {
'basejstemplate' : JsTemplateBaseNode,
'ichtemplate' : IchTemplateNode,
}
TAG_NAME_TEMPLATE = "include_%s"
def compilation_function_factory(node_klass):
"""
returns a compilation function that
will use the builtin do_include to generate
a node containing the rendered meta template,
then pass it to the constuctor of the given
node_klass to be wrapped.
"""
def compilation_function(parser, token):
returned_node = do_include(parser, token)
return node_klass(returned_node)
return compilation_function
for tag_type, node_klass in register_hash.items():
tag_name = TAG_NAME_TEMPLATE % tag_type
compilation_function = compilation_function_factory(node_klass)
register.tag(tag_name, compilation_function)