Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Delta Between Two Patch Sets: sitescripts/cms/converters.py

Issue 6439145228468224: Added custom template loader to CMS in order to enable {% include %} and {% import %} in jinja temp… (Closed)
Left Patch Set: Created Dec. 11, 2013, 6:31 p.m.
Right Patch Set: Only allow inlcudes with escaped brackets in markdown Created Dec. 12, 2013, 1:48 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « no previous file | sitescripts/utils.py » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 # coding: utf-8 1 # coding: utf-8
2 2
3 # This file is part of the Adblock Plus web scripts, 3 # This file is part of the Adblock Plus web scripts,
4 # Copyright (C) 2006-2013 Eyeo GmbH 4 # Copyright (C) 2006-2013 Eyeo GmbH
5 # 5 #
6 # Adblock Plus is free software: you can redistribute it and/or modify 6 # Adblock Plus is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License version 3 as 7 # it under the terms of the GNU General Public License version 3 as
8 # published by the Free Software Foundation. 8 # published by the Free Software Foundation.
9 # 9 #
10 # Adblock Plus is distributed in the hope that it will be useful, 10 # Adblock Plus is distributed in the hope that it will be useful,
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
108 url = new_url 108 url = new_url
109 if attr == "href": 109 if attr == "href":
110 post += ' hreflang="%s"' % jinja2.Markup.escape(locale) 110 post += ' hreflang="%s"' % jinja2.Markup.escape(locale)
111 111
112 return "".join((pre, jinja2.Markup.escape(url), post)) 112 return "".join((pre, jinja2.Markup.escape(url), post))
113 113
114 text = re.sub(r"(<a\s[^<>]*\b(href)=\")([^<>\"]+)(\")", process_link, text) 114 text = re.sub(r"(<a\s[^<>]*\b(href)=\")([^<>\"]+)(\")", process_link, text)
115 text = re.sub(r"(<img\s[^<>]*\b(src)=\")([^<>\"]+)(\")", process_link, text) 115 text = re.sub(r"(<img\s[^<>]*\b(src)=\")([^<>\"]+)(\")", process_link, text)
116 return text 116 return text
117 117
118 include_start_regex = '<'
119 include_end_regex = '>'
120
118 def resolve_includes(self, text): 121 def resolve_includes(self, text):
119 def resolve_include(match): 122 def resolve_include(match):
120 global converters 123 global converters
121 name = match.group(1) 124 name = match.group(1)
122 for format, converter_class in converters.iteritems(): 125 for format, converter_class in converters.iteritems():
123 if self._params["source"].has_include(name, format): 126 if self._params["source"].has_include(name, format):
124 self._params["includedata"] = self._params["source"].read_include(name , format) 127 self._params["includedata"] = self._params["source"].read_include(name , format)
125 converter = converter_class(self._params, key="includedata") 128 converter = converter_class(self._params, key="includedata")
126 return converter() 129 return converter()
127 raise Exception("Failed to resolve include %s in page %s" % (name, self._p arams["page"])) 130 raise Exception("Failed to resolve include %s in page %s" % (name, self._p arams["page"]))
128 131
129 return re.sub(r'<\?\s*include\s+([^\s<>"]+)\s*\?>', resolve_include, text) 132 return re.sub(
133 r'%s\?\s*include\s+([^\s<>"]+)\s*\?%s' % (
134 self.include_start_regex,
135 self.include_end_regex
136 ),
137 resolve_include,
138 text
139 )
130 140
131 def __call__(self): 141 def __call__(self):
132 result = self.get_html(self._params[self._key]) 142 result = self.get_html(self._params[self._key])
133 result = self.resolve_includes(result) 143 result = self.resolve_includes(result)
134 if self._key == "pagedata": 144 if self._key == "pagedata":
135 head = [] 145 head = []
136 def add_to_head(match): 146 def add_to_head(match):
137 head.append(match.group(1)) 147 head.append(match.group(1))
138 return "" 148 return ""
139 body = re.sub(r"<head>(.*?)</head>", add_to_head, result, flags=re.S) 149 body = re.sub(r"<head>(.*?)</head>", add_to_head, result, flags=re.S)
140 return "".join(head), body 150 return "".join(head), body
141 else: 151 else:
142 return result 152 return result
143 153
144 class RawConverter(Converter): 154 class RawConverter(Converter):
145 def get_html(self, source): 155 def get_html(self, source):
146 result = self.insert_localized_strings(source, html_escapes) 156 result = self.insert_localized_strings(source, html_escapes)
147 result = self.process_links(result) 157 result = self.process_links(result)
148 return result 158 return result
149 159
150 class MarkdownConverter(Converter): 160 class MarkdownConverter(Converter):
161 include_start_regex = r'(?:%s|%s)' % (
162 Converter.include_start_regex,
163 re.escape(jinja2.escape(Converter.include_start_regex))
164 )
165 include_end_regex = r'(?:%s|%s)' % (
166 Converter.include_end_regex,
167 re.escape(jinja2.escape(Converter.include_end_regex))
168 )
169
151 def get_html(self, source): 170 def get_html(self, source):
152 def remove_unnecessary_entities(match): 171 def remove_unnecessary_entities(match):
153 char = unichr(int(match.group(1))) 172 char = unichr(int(match.group(1)))
154 if char in html_escapes: 173 if char in html_escapes:
155 return match.group(0) 174 return match.group(0)
156 else: 175 else:
157 return char 176 return char
158 177
159 escapes = {} 178 escapes = {}
160 for char in markdown.Markdown.ESCAPED_CHARS: 179 for char in markdown.Markdown.ESCAPED_CHARS:
161 escapes[char] = "&#" + str(ord(char)) + ";" 180 escapes[char] = "&#" + str(ord(char)) + ";"
162 for key, value in html_escapes.iteritems(): 181 for key, value in html_escapes.iteritems():
163 escapes[key] = value 182 escapes[key] = value
164 183
165 md = markdown.Markdown(output="html5", extensions=["attr_list"]) 184 md = markdown.Markdown(output="html5", extensions=["attr_list"])
166 md.preprocessors["html_block"].markdown_in_raw = True 185 md.preprocessors["html_block"].markdown_in_raw = True
167 186
168 result = self.insert_localized_strings(source, escapes) 187 result = self.insert_localized_strings(source, escapes)
169 result = md.convert(result) 188 result = md.convert(result)
170 result = re.sub(r"&#(\d+);", remove_unnecessary_entities, result) 189 result = re.sub(r"&#(\d+);", remove_unnecessary_entities, result)
171 result = self.process_links(result) 190 result = self.process_links(result)
172 return result 191 return result
173 192
174 class TemplateConverter(Converter): 193 class TemplateConverter(Converter):
194 class _SourceLoader(jinja2.BaseLoader):
195 def __init__(self, source):
196 self.source = source
197
198 def get_source(self, environment, template):
199 try:
200 return self.source.read_file(template + ".tmpl"), None, None
201 except Exception:
202 raise jinja2.TemplateNotFound(template)
203
175 def __init__(self, *args, **kwargs): 204 def __init__(self, *args, **kwargs):
176 Converter.__init__(self, *args, **kwargs) 205 Converter.__init__(self, *args, **kwargs)
177 206
178 filters = { 207 filters = {
179 "translate": self.translate, 208 "translate": self.translate,
180 "linkify": self.linkify, 209 "linkify": self.linkify,
181 "toclist": self.toclist, 210 "toclist": self.toclist,
182 } 211 }
183 212
184 for filename in self._params["source"].list_files("filters"): 213 for filename in self._params["source"].list_files("filters"):
185 root, ext = os.path.splitext(filename) 214 root, ext = os.path.splitext(filename)
186 if ext.lower() != ".py": 215 if ext.lower() != ".py":
187 continue 216 continue
188 217
189 path = "%s/%s" % ("filters", filename) 218 path = "%s/%s" % ("filters", filename)
190 code = self._params["source"].read_file(path) 219 code = self._params["source"].read_file(path)
191 module = imp.new_module(root.replace("/", ".")) 220 module = imp.new_module(root.replace("/", "."))
192 exec code in module.__dict__ 221 exec code in module.__dict__
193 222
194 func = os.path.basename(root) 223 func = os.path.basename(root)
195 if not hasattr(module, func): 224 if not hasattr(module, func):
196 raise Exception("Expected function %s not found in filter file %s" % (fu nc, filename)) 225 raise Exception("Expected function %s not found in filter file %s" % (fu nc, filename))
197 filters[func] = getattr(module, func) 226 filters[func] = getattr(module, func)
198 filters[func].module_ref = module # Prevent garbage collection 227 filters[func].module_ref = module # Prevent garbage collection
199 228
200 self._env = get_custom_template_environment(filters, self._params["source"]. get_template_loader()) 229 self._env = get_custom_template_environment(filters, self._SourceLoader(self ._params["source"]))
201 230
202 def get_html(self, source): 231 def get_html(self, source):
203 template = self._env.from_string(source) 232 template = self._env.from_string(source)
204 return template.render(self._params) 233 return template.render(self._params)
205 234
206 def translate(self, name, page=None, links=[]): 235 def translate(self, name, page=None, links=[]):
207 if page == None: 236 if page == None:
208 localedata = self._params["localedata"] 237 localedata = self._params["localedata"]
209 else: 238 else:
210 localedata = self._params["source"].read_locale(self._params["locale"], pa ge) 239 localedata = self._params["source"].read_locale(self._params["locale"], pa ge)
(...skipping 26 matching lines...) Expand all
237 stack.pop() 266 stack.pop()
238 stack[-1]["subitems"].append(item) 267 stack[-1]["subitems"].append(item)
239 stack.append(item) 268 stack.append(item)
240 return structured 269 return structured
241 270
242 converters = { 271 converters = {
243 "raw": RawConverter, 272 "raw": RawConverter,
244 "md": MarkdownConverter, 273 "md": MarkdownConverter,
245 "tmpl": TemplateConverter, 274 "tmpl": TemplateConverter,
246 } 275 }
LEFTRIGHT

Powered by Google App Engine
This is Rietveld