forked from openedx/edx-platform
-
Notifications
You must be signed in to change notification settings - Fork 2
/
template_block.py
147 lines (121 loc) · 4.55 KB
/
template_block.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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
"""
Template block
"""
from string import Template
from xblock.core import XBlock
from lxml import etree
from web_fragments.fragment import Fragment
from xmodule.editing_block import EditingMixin
from xmodule.raw_block import RawMixin
from xmodule.util.builtin_assets import add_webpack_js_to_fragment, add_sass_to_fragment
from xmodule.x_module import (
ResourceTemplates,
shim_xmodule_js,
XModuleMixin,
XModuleToXBlockMixin,
)
from xmodule.xml_block import XmlMixin
from openedx.core.djangolib.markup import Text
class CustomTagTemplateBlock( # pylint: disable=abstract-method
RawMixin,
XmlMixin,
EditingMixin,
XModuleToXBlockMixin,
ResourceTemplates,
XModuleMixin,
):
"""
A block which provides templates for CustomTagBlock. The template name
is set on the `impl` attribute of CustomTagBlock. See below for more details
on how to use it.
"""
@XBlock.needs('mako')
class CustomTagBlock(CustomTagTemplateBlock): # pylint: disable=abstract-method
"""
This block supports tags of the form
<customtag option="val" option2="val2" impl="tagname"/>
In this case, $tagname should refer to a file in data/custom_tags, which
contains a Python string.Template formatted template that uses ${option} and
${option2} for the content.
For instance:
data/mycourse/custom_tags/book::
More information given in <a href="/book/${page}">the text</a>
course.xml::
...
<customtag page="234" impl="book"/>
...
Renders to::
More information given in <a href="/book/234">the text</a>
"""
resources_dir = None
template_dir_name = 'customtag'
def studio_view(self, _context):
"""
Return the studio view.
"""
fragment = Fragment(
self.runtime.service(self, 'mako').render_cms_template(self.mako_template, self.get_context())
)
add_sass_to_fragment(fragment, 'CustomTagBlockEditor.scss')
add_webpack_js_to_fragment(fragment, 'CustomTagBlockEditor')
shim_xmodule_js(fragment, 'XMLEditingDescriptor')
return fragment
def render_template(self, system, xml_data):
'''Render the template, given the definition xml_data'''
xmltree = etree.fromstring(xml_data)
if 'impl' in xmltree.attrib:
template_name = xmltree.attrib['impl']
else:
# VS[compat] backwards compatibility with old nested customtag structure
child_impl = xmltree.find('impl')
if child_impl is not None:
template_name = child_impl.text
else:
# TODO (vshnayder): better exception type
raise Exception("Could not find impl attribute in customtag {}"
.format(self.location))
params = dict(list(xmltree.items()))
# cdodge: look up the template as a module
template_loc = self.location.replace(category='custom_tag_template', name=template_name)
template_block = system.get_block(template_loc)
template_block_data = template_block.data
template = Template(template_block_data)
return template.safe_substitute(params)
@property
def rendered_html(self):
return self.render_template(self.runtime, self.data)
def student_view(self, _context):
"""
Renders the student view.
"""
fragment = Fragment()
fragment.add_content(self.rendered_html)
return fragment
def export_to_file(self):
"""
Custom tags are special: since they're already pointers, we don't want
to export them in a file with yet another layer of indirection.
"""
return False
class TranslateCustomTagBlock( # pylint: disable=abstract-method
XModuleToXBlockMixin,
XModuleMixin,
):
"""
Converts olx of the form `<$custom_tag attr="" attr=""/>` to CustomTagBlock
of the form `<customtag attr="" attr="" impl="$custom_tag"/>`.
"""
resources_dir = None
@classmethod
def parse_xml(cls, node, runtime, _keys):
"""
Transforms the xml_data from <$custom_tag attr="" attr=""/> to
<customtag attr="" attr="" impl="$custom_tag"/>
"""
runtime.error_tracker(Text('WARNING: the <{tag}> tag is deprecated. '
'Instead, use <customtag impl="{tag}" attr1="..." attr2="..."/>. ')
.format(tag=node.tag))
tag = node.tag
node.tag = 'customtag'
node.attrib['impl'] = tag
return runtime.process_xml(etree.tostring(node))