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

Side by Side Diff: cms/converters.py

Issue 29345291: Noissue - Adapt quotes for compliance with our coding style in the CMS (Closed)
Patch Set: Created May 29, 2016, 1:27 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « cms/bin/translate.py ('k') | cms/sources.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # This file is part of the Adblock Plus web scripts, 1 # This file is part of the Adblock Plus web scripts,
2 # Copyright (C) 2006-2016 Eyeo GmbH 2 # Copyright (C) 2006-2016 Eyeo GmbH
3 # 3 #
4 # Adblock Plus is free software: you can redistribute it and/or modify 4 # Adblock Plus is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License version 3 as 5 # it under the terms of the GNU General Public License version 3 as
6 # published by the Free Software Foundation. 6 # published by the Free Software Foundation.
7 # 7 #
8 # Adblock Plus is distributed in the hope that it will be useful, 8 # Adblock Plus is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of 9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details. 11 # GNU General Public License for more details.
12 # 12 #
13 # You should have received a copy of the GNU General Public License 13 # You should have received a copy of the GNU General Public License
14 # along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. 14 # along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
15 15
16 import os 16 import os
17 import HTMLParser 17 import HTMLParser
18 import re 18 import re
19 19
20 import jinja2 20 import jinja2
21 import markdown 21 import markdown
22 22
23 23
24 # Monkey-patch Markdown's isBlockLevel function to ensure that no paragraphs are 24 # Monkey-patch Markdown's isBlockLevel function to ensure that no paragraphs are
25 # inserted into the <head> tag 25 # inserted into the <head> tag
26 orig_isBlockLevel = markdown.util.isBlockLevel 26 orig_isBlockLevel = markdown.util.isBlockLevel
27 27
28 28
29 def isBlockLevel(tag): 29 def isBlockLevel(tag):
30 if tag == "head": 30 if tag == 'head':
31 return True 31 return True
32 else: 32 else:
33 return orig_isBlockLevel(tag) 33 return orig_isBlockLevel(tag)
34 markdown.util.isBlockLevel = isBlockLevel 34 markdown.util.isBlockLevel = isBlockLevel
35 35
36 html_escapes = { 36 html_escapes = {
37 "<": "&lt;", 37 '<': '&lt;',
38 ">": "&gt;", 38 '>': '&gt;',
39 "&": "&amp;", 39 '&': '&amp;',
40 "\"": "&quot;", 40 '"': '&quot;',
41 "'": "&#39;", 41 "'": '&#39;',
42 } 42 }
43 43
44 44
45 class AttributeParser(HTMLParser.HTMLParser): 45 class AttributeParser(HTMLParser.HTMLParser):
46 _string = None 46 _string = None
47 _inside_fixed = False 47 _inside_fixed = False
48 _fixed_strings = None 48 _fixed_strings = None
49 _attrs = None 49 _attrs = None
50 50
51 def __init__(self, whitelist): 51 def __init__(self, whitelist):
52 self._whitelist = whitelist 52 self._whitelist = whitelist
53 53
54 def parse(self, text, pagename): 54 def parse(self, text, pagename):
55 self.reset() 55 self.reset()
56 self._string = [] 56 self._string = []
57 self._fixed_strings = [] 57 self._fixed_strings = []
58 self._inside_fixed = False 58 self._inside_fixed = False
59 self._attrs = {} 59 self._attrs = {}
60 self._pagename = pagename 60 self._pagename = pagename
61 61
62 # Force-escape ampersands, otherwise the parser will autocomplete bogus 62 # Force-escape ampersands, otherwise the parser will autocomplete bogus
63 # entities. 63 # entities.
64 text = re.sub(r"&(?!\S+;)", "&amp;", text) 64 text = re.sub(r'&(?!\S+;)', '&amp;', text)
65 65
66 try: 66 try:
67 self.feed(text) 67 self.feed(text)
68 return "".join(self._string), self._attrs, ["".join(s) for s in self ._fixed_strings] 68 return ''.join(self._string), self._attrs, [''.join(s) for s in self ._fixed_strings]
69 finally: 69 finally:
70 self._string = None 70 self._string = None
71 self._attrs = None 71 self._attrs = None
72 self._pagename = None 72 self._pagename = None
73 self._inside_fixed = False 73 self._inside_fixed = False
74 self._fixed_strings = None 74 self._fixed_strings = None
75 75
76 def handle_starttag(self, tag, attrs): 76 def handle_starttag(self, tag, attrs):
77 if self._inside_fixed: 77 if self._inside_fixed:
78 raise Exception("Unexpected HTML tag '%s' inside a fixed string on p age %s" % (tag, self._pagename)) 78 raise Exception("Unexpected HTML tag '%s' inside a fixed string on p age %s" % (tag, self._pagename))
79 elif tag == "fix": 79 elif tag == 'fix':
80 self._inside_fixed = True 80 self._inside_fixed = True
81 self._fixed_strings.append([]) 81 self._fixed_strings.append([])
82 elif tag in self._whitelist: 82 elif tag in self._whitelist:
83 self._attrs.setdefault(tag, []).append(attrs) 83 self._attrs.setdefault(tag, []).append(attrs)
84 self._string.append("<%s>" % tag) 84 self._string.append('<%s>' % tag)
85 else: 85 else:
86 raise Exception("Unexpected HTML tag '%s' in localizable string on p age %s" % (tag, self._pagename)) 86 raise Exception("Unexpected HTML tag '%s' in localizable string on p age %s" % (tag, self._pagename))
87 87
88 def handle_endtag(self, tag): 88 def handle_endtag(self, tag):
89 if tag == "fix": 89 if tag == 'fix':
90 self._string.append("{%d}" % len(self._fixed_strings)) 90 self._string.append('{%d}' % len(self._fixed_strings))
91 self._inside_fixed = False 91 self._inside_fixed = False
92 else: 92 else:
93 self._string.append("</%s>" % tag) 93 self._string.append('</%s>' % tag)
94 94
95 def _append_text(self, s): 95 def _append_text(self, s):
96 if self._inside_fixed: 96 if self._inside_fixed:
97 self._fixed_strings[-1].append(s) 97 self._fixed_strings[-1].append(s)
98 else: 98 else:
99 self._string.append(s) 99 self._string.append(s)
100 100
101 def handle_data(self, data): 101 def handle_data(self, data):
102 # Note: lack of escaping here is intentional. The result is a locale str ing, 102 # Note: lack of escaping here is intentional. The result is a locale str ing,
103 # HTML escaping is applied when this string is inserted into the documen t. 103 # HTML escaping is applied when this string is inserted into the documen t.
104 self._append_text(data) 104 self._append_text(data)
105 105
106 def handle_entityref(self, name): 106 def handle_entityref(self, name):
107 self._append_text(self.unescape("&%s;" % name)) 107 self._append_text(self.unescape('&%s;' % name))
108 108
109 def handle_charref(self, name): 109 def handle_charref(self, name):
110 self._append_text(self.unescape("&#%s;" % name)) 110 self._append_text(self.unescape('&#%s;' % name))
111 111
112 112
113 class Converter: 113 class Converter:
114 whitelist = {"a", "em", "sup", "strong", "code", "span"} 114 whitelist = {'a', 'em', 'sup', 'strong', 'code', 'span'}
115 missing_translations = 0 115 missing_translations = 0
116 total_translations = 0 116 total_translations = 0
117 117
118 def __init__(self, params, key="pagedata"): 118 def __init__(self, params, key='pagedata'):
119 self._params = params 119 self._params = params
120 self._key = key 120 self._key = key
121 self._attribute_parser = AttributeParser(self.whitelist) 121 self._attribute_parser = AttributeParser(self.whitelist)
122 self._seen_defaults = {} 122 self._seen_defaults = {}
123 123
124 # Read in any parameters specified at the beginning of the file 124 # Read in any parameters specified at the beginning of the file
125 data, filename = params[key] 125 data, filename = params[key]
126 lines = data.splitlines(True) 126 lines = data.splitlines(True)
127 for i, line in enumerate(lines): 127 for i, line in enumerate(lines):
128 if not re.search(r"^\s*[\w\-]+\s*=", line): 128 if not re.search(r'^\s*[\w\-]+\s*=', line):
129 break 129 break
130 name, value = line.split("=", 1) 130 name, value = line.split('=', 1)
131 params[name.strip()] = value.strip() 131 params[name.strip()] = value.strip()
132 lines[i] = "\n" 132 lines[i] = '\n'
133 params[key] = ("".join(lines), filename) 133 params[key] = (''.join(lines), filename)
134 134
135 def localize_string(self, page, name, default, comment, localedata, escapes) : 135 def localize_string(self, page, name, default, comment, localedata, escapes) :
136 def escape(s): 136 def escape(s):
137 return re.sub(r".", 137 return re.sub(r'.',
138 lambda match: escapes.get(match.group(0), match.group( 0)), 138 lambda match: escapes.get(match.group(0), match.group( 0)),
139 s, flags=re.S) 139 s, flags=re.S)
140 140
141 def re_escape(s): 141 def re_escape(s):
142 return re.escape(escape(s)) 142 return re.escape(escape(s))
143 143
144 # Handle duplicated strings 144 # Handle duplicated strings
145 if default: 145 if default:
146 self._seen_defaults[(page, name)] = (default, comment) 146 self._seen_defaults[(page, name)] = (default, comment)
147 else: 147 else:
148 try: 148 try:
149 default, comment = self._seen_defaults[(page, name)] 149 default, comment = self._seen_defaults[(page, name)]
150 except KeyError: 150 except KeyError:
151 raise Exception("Text not yet defined for string %s on page %s" % 151 raise Exception('Text not yet defined for string %s on page %s' %
152 (name, page)) 152 (name, page))
153 153
154 # Extract tag attributes from default string 154 # Extract tag attributes from default string
155 default, saved_attributes, fixed_strings = self._attribute_parser.parse( default, self._params["page"]) 155 default, saved_attributes, fixed_strings = self._attribute_parser.parse( default, self._params['page'])
156 156
157 # Get translation 157 # Get translation
158 locale = self._params["locale"] 158 locale = self._params['locale']
159 if locale == self._params["defaultlocale"]: 159 if locale == self._params['defaultlocale']:
160 result = default 160 result = default
161 elif name in localedata: 161 elif name in localedata:
162 result = localedata[name].strip() 162 result = localedata[name].strip()
163 else: 163 else:
164 result = default 164 result = default
165 self.missing_translations += 1 165 self.missing_translations += 1
166 self.total_translations += 1 166 self.total_translations += 1
167 167
168 # Perform callback with the string if required, e.g. for the translation s script 168 # Perform callback with the string if required, e.g. for the translation s script
169 callback = self._params["localized_string_callback"] 169 callback = self._params['localized_string_callback']
170 if callback: 170 if callback:
171 callback(page, locale, name, result, comment, fixed_strings) 171 callback(page, locale, name, result, comment, fixed_strings)
172 172
173 # Insert fixed strings 173 # Insert fixed strings
174 for i, fixed_string in enumerate(fixed_strings, 1): 174 for i, fixed_string in enumerate(fixed_strings, 1):
175 result = result.replace("{%d}" % i, fixed_string) 175 result = result.replace('{%d}' % i, fixed_string)
176 176
177 # Insert attributes 177 # Insert attributes
178 result = escape(result) 178 result = escape(result)
179 179
180 def stringify_attribute((name, value)): 180 def stringify_attribute((name, value)):
181 return '%s="%s"' % ( 181 return '%s="%s"' % (
182 escape(name), 182 escape(name),
183 escape(self.insert_localized_strings(value, {})) 183 escape(self.insert_localized_strings(value, {}))
184 ) 184 )
185 185
186 for tag in self.whitelist: 186 for tag in self.whitelist:
187 allowed_contents = "(?:[^<>]|%s)" % "|".join(( 187 allowed_contents = '(?:[^<>]|%s)' % '|'.join((
188 "<(?:%s[^<>]*?|/%s)>" % (t, t) 188 '<(?:%s[^<>]*?|/%s)>' % (t, t)
189 for t in map(re.escape, self.whitelist - {tag}) 189 for t in map(re.escape, self.whitelist - {tag})
190 )) 190 ))
191 saved = saved_attributes.get(tag, []) 191 saved = saved_attributes.get(tag, [])
192 for attrs in saved: 192 for attrs in saved:
193 attrs = map(stringify_attribute, attrs) 193 attrs = map(stringify_attribute, attrs)
194 result = re.sub( 194 result = re.sub(
195 r"%s(%s*?)%s" % (re_escape("<%s>" % tag), allowed_contents, 195 r'%s(%s*?)%s' % (re_escape('<%s>' % tag), allowed_contents,
196 re_escape("</%s>" % tag)), 196 re_escape('</%s>' % tag)),
197 lambda match: r'<%s%s>%s</%s>' % ( 197 lambda match: r'<%s%s>%s</%s>' % (
198 tag, 198 tag,
199 " " + " ".join(attrs) if attrs else "", 199 ' ' + ' '.join(attrs) if attrs else '',
200 match.group(1), 200 match.group(1),
201 tag 201 tag
202 ), 202 ),
203 result, 1, flags=re.S 203 result, 1, flags=re.S
204 ) 204 )
205 result = re.sub( 205 result = re.sub(
206 r"%s(%s*?)%s" % (re_escape("<%s>" % tag), allowed_contents, 206 r'%s(%s*?)%s' % (re_escape('<%s>' % tag), allowed_contents,
207 re_escape("</%s>" % tag)), 207 re_escape('</%s>' % tag)),
208 r"<%s>\1</%s>" % (tag, tag), 208 r'<%s>\1</%s>' % (tag, tag),
209 result, flags=re.S 209 result, flags=re.S
210 ) 210 )
211 return result 211 return result
212 212
213 def insert_localized_strings(self, text, escapes, to_html=lambda s: s): 213 def insert_localized_strings(self, text, escapes, to_html=lambda s: s):
214 def lookup_string(match): 214 def lookup_string(match):
215 name, comment, default = match.groups() 215 name, comment, default = match.groups()
216 if default: 216 if default:
217 default = to_html(default).strip() 217 default = to_html(default).strip()
218 return self.localize_string(self._params["page"], name, default, 218 return self.localize_string(self._params['page'], name, default,
219 comment, self._params["localedata"], esc apes) 219 comment, self._params['localedata'], esc apes)
220 220
221 return re.sub( 221 return re.sub(
222 r"{{\s*" 222 r'{{\s*'
223 r"([\w\-]+)" # String ID 223 r'([\w\-]+)' # String ID
224 r"(?:(?:\[(.*?)\])?" # Optional comment 224 r'(?:(?:\[(.*?)\])?' # Optional comment
225 r"\s+" 225 r'\s+'
226 r"((?:(?!{{).|" # Translatable text 226 r'((?:(?!{{).|' # Translatable text
227 r"{{(?:(?!}}).)*}}" # Nested translation 227 r'{{(?:(?!}}).)*}}' # Nested translation
228 r")*?)" 228 r')*?)'
229 r")?" 229 r')?'
230 r"}}", 230 r'}}',
231 lookup_string, 231 lookup_string,
232 text, 232 text,
233 flags=re.S 233 flags=re.S
234 ) 234 )
235 235
236 def process_links(self, text): 236 def process_links(self, text):
237 def process_link(match): 237 def process_link(match):
238 pre, attr, url, post = match.groups() 238 pre, attr, url, post = match.groups()
239 url = jinja2.Markup(url).unescape() 239 url = jinja2.Markup(url).unescape()
240 240
241 locale, new_url = self._params["source"].resolve_link(url, self._par ams["locale"]) 241 locale, new_url = self._params['source'].resolve_link(url, self._par ams['locale'])
242 if new_url != None: 242 if new_url != None:
243 url = new_url 243 url = new_url
244 if attr == "href": 244 if attr == 'href':
245 post += ' hreflang="%s"' % jinja2.Markup.escape(locale) 245 post += ' hreflang="%s"' % jinja2.Markup.escape(locale)
246 246
247 return "".join((pre, jinja2.Markup.escape(url), post)) 247 return ''.join((pre, jinja2.Markup.escape(url), post))
248 248
249 text = re.sub(r"(<a\s[^<>]*\b(href)=\")([^<>\"]+)(\")", process_link, te xt) 249 text = re.sub(r'(<a\s[^<>]*\b(href)=\")([^<>\"]+)(\")', process_link, te xt)
250 text = re.sub(r"(<img\s[^<>]*\b(src)=\")([^<>\"]+)(\")", process_link, t ext) 250 text = re.sub(r'(<img\s[^<>]*\b(src)=\")([^<>\"]+)(\")', process_link, t ext)
251 return text 251 return text
252 252
253 include_start_regex = '<' 253 include_start_regex = '<'
254 include_end_regex = '>' 254 include_end_regex = '>'
255 255
256 def resolve_includes(self, text): 256 def resolve_includes(self, text):
257 def resolve_include(match): 257 def resolve_include(match):
258 global converters 258 global converters
259 name = match.group(1) 259 name = match.group(1)
260 for format, converter_class in converters.iteritems(): 260 for format, converter_class in converters.iteritems():
261 if self._params["source"].has_include(name, format): 261 if self._params['source'].has_include(name, format):
262 self._params["includedata"] = self._params["source"].read_in clude(name, format) 262 self._params['includedata'] = self._params['source'].read_in clude(name, format)
263 converter = converter_class(self._params, key="includedata") 263 converter = converter_class(self._params, key='includedata')
264 result = converter() 264 result = converter()
265 self.missing_translations += converter.missing_translations 265 self.missing_translations += converter.missing_translations
266 self.total_translations += converter.total_translations 266 self.total_translations += converter.total_translations
267 return result 267 return result
268 raise Exception("Failed to resolve include %s on page %s" % (name, s elf._params["page"])) 268 raise Exception('Failed to resolve include %s on page %s' % (name, s elf._params['page']))
269 269
270 return re.sub( 270 return re.sub(
271 r'%s\?\s*include\s+([^\s<>"]+)\s*\?%s' % ( 271 r'%s\?\s*include\s+([^\s<>"]+)\s*\?%s' % (
272 self.include_start_regex, 272 self.include_start_regex,
273 self.include_end_regex 273 self.include_end_regex
274 ), 274 ),
275 resolve_include, 275 resolve_include,
276 text 276 text
277 ) 277 )
278 278
279 def __call__(self): 279 def __call__(self):
280 result = self.get_html(*self._params[self._key]) 280 result = self.get_html(*self._params[self._key])
281 result = self.resolve_includes(result) 281 result = self.resolve_includes(result)
282 if self._key == "pagedata": 282 if self._key == 'pagedata':
283 head = [] 283 head = []
284 284
285 def add_to_head(match): 285 def add_to_head(match):
286 head.append(match.group(1)) 286 head.append(match.group(1))
287 return "" 287 return ''
288 body = re.sub(r"<head>(.*?)</head>", add_to_head, result, flags=re.S ) 288 body = re.sub(r'<head>(.*?)</head>', add_to_head, result, flags=re.S )
289 return "".join(head), body 289 return ''.join(head), body
290 else: 290 else:
291 return result 291 return result
292 292
293 293
294 class RawConverter(Converter): 294 class RawConverter(Converter):
295 def get_html(self, source, filename): 295 def get_html(self, source, filename):
296 result = self.insert_localized_strings(source, html_escapes) 296 result = self.insert_localized_strings(source, html_escapes)
297 result = self.process_links(result) 297 result = self.process_links(result)
298 return result 298 return result
299 299
(...skipping 11 matching lines...) Expand all
311 def get_html(self, source, filename): 311 def get_html(self, source, filename):
312 def remove_unnecessary_entities(match): 312 def remove_unnecessary_entities(match):
313 char = unichr(int(match.group(1))) 313 char = unichr(int(match.group(1)))
314 if char in html_escapes: 314 if char in html_escapes:
315 return match.group(0) 315 return match.group(0)
316 else: 316 else:
317 return char 317 return char
318 318
319 escapes = {} 319 escapes = {}
320 for char in markdown.Markdown.ESCAPED_CHARS: 320 for char in markdown.Markdown.ESCAPED_CHARS:
321 escapes[char] = "&#" + str(ord(char)) + ";" 321 escapes[char] = '&#' + str(ord(char)) + ';'
322 for key, value in html_escapes.iteritems(): 322 for key, value in html_escapes.iteritems():
323 escapes[key] = value 323 escapes[key] = value
324 324
325 md = markdown.Markdown(output="html5", extensions=["extra"]) 325 md = markdown.Markdown(output='html5', extensions=['extra'])
326 md.preprocessors["html_block"].markdown_in_raw = True 326 md.preprocessors['html_block'].markdown_in_raw = True
327 327
328 def to_html(s): 328 def to_html(s):
329 return re.sub(r'</?p>', '', md.convert(s)) 329 return re.sub(r'</?p>', '', md.convert(s))
330 330
331 result = self.insert_localized_strings(source, escapes, to_html) 331 result = self.insert_localized_strings(source, escapes, to_html)
332 result = md.convert(result) 332 result = md.convert(result)
333 result = re.sub(r"&#(\d+);", remove_unnecessary_entities, result) 333 result = re.sub(r'&#(\d+);', remove_unnecessary_entities, result)
334 result = self.process_links(result) 334 result = self.process_links(result)
335 return result 335 return result
336 336
337 337
338 class SourceTemplateLoader(jinja2.BaseLoader): 338 class SourceTemplateLoader(jinja2.BaseLoader):
339 def __init__(self, source): 339 def __init__(self, source):
340 self.source = source 340 self.source = source
341 341
342 def get_source(self, environment, template): 342 def get_source(self, environment, template):
343 try: 343 try:
344 result = self.source.read_file(template + ".tmpl") 344 result = self.source.read_file(template + '.tmpl')
345 except Exception: 345 except Exception:
346 raise jinja2.TemplateNotFound(template) 346 raise jinja2.TemplateNotFound(template)
347 return result + (None,) 347 return result + (None,)
348 348
349 349
350 class TemplateConverter(Converter): 350 class TemplateConverter(Converter):
351 def __init__(self, *args, **kwargs): 351 def __init__(self, *args, **kwargs):
352 Converter.__init__(self, *args, **kwargs) 352 Converter.__init__(self, *args, **kwargs)
353 353
354 filters = { 354 filters = {
355 "translate": self.translate, 355 'translate': self.translate,
356 "linkify": self.linkify, 356 'linkify': self.linkify,
357 "toclist": self.toclist, 357 'toclist': self.toclist,
358 } 358 }
359 359
360 globals = { 360 globals = {
361 "get_string": self.get_string, 361 'get_string': self.get_string,
362 "get_page_content": self.get_page_content, 362 'get_page_content': self.get_page_content,
363 } 363 }
364 364
365 for dirname, dictionary in [("filters", filters), ("globals", globals)]: 365 for dirname, dictionary in [('filters', filters), ('globals', globals)]:
366 for filename in self._params["source"].list_files(dirname): 366 for filename in self._params['source'].list_files(dirname):
367 root, ext = os.path.splitext(filename) 367 root, ext = os.path.splitext(filename)
368 if ext.lower() != ".py": 368 if ext.lower() != '.py':
369 continue 369 continue
370 370
371 path = "%s/%s" % (dirname, filename) 371 path = '%s/%s' % (dirname, filename)
372 namespace = self._params["source"].exec_file(path) 372 namespace = self._params['source'].exec_file(path)
373 373
374 name = os.path.basename(root) 374 name = os.path.basename(root)
375 try: 375 try:
376 dictionary[name] = namespace[name] 376 dictionary[name] = namespace[name]
377 except KeyError: 377 except KeyError:
378 raise Exception("Expected symbol %r not found in %r" % (name , path)) 378 raise Exception('Expected symbol %r not found in %r' % (name , path))
379 379
380 self._env = jinja2.Environment(loader=SourceTemplateLoader(self._params[ "source"]), autoescape=True) 380 self._env = jinja2.Environment(loader=SourceTemplateLoader(self._params[ 'source']), autoescape=True)
381 self._env.filters.update(filters) 381 self._env.filters.update(filters)
382 self._env.globals.update(globals) 382 self._env.globals.update(globals)
383 383
384 def get_html(self, source, filename): 384 def get_html(self, source, filename):
385 env = self._env 385 env = self._env
386 code = env.compile(source, None, filename) 386 code = env.compile(source, None, filename)
387 template = jinja2.Template.from_code(env, code, env.globals) 387 template = jinja2.Template.from_code(env, code, env.globals)
388 388
389 try: 389 try:
390 module = template.make_module(self._params) 390 module = template.make_module(self._params)
391 except Exception: 391 except Exception:
392 env.handle_exception() 392 env.handle_exception()
393 393
394 for key, value in module.__dict__.iteritems(): 394 for key, value in module.__dict__.iteritems():
395 if not key.startswith("_"): 395 if not key.startswith('_'):
396 self._params[key] = value 396 self._params[key] = value
397 397
398 result = unicode(module) 398 result = unicode(module)
399 result = self.process_links(result) 399 result = self.process_links(result)
400 return result 400 return result
401 401
402 def translate(self, default, name, comment=None): 402 def translate(self, default, name, comment=None):
403 return jinja2.Markup(self.localize_string( 403 return jinja2.Markup(self.localize_string(
404 self._params["page"], name, default, comment, 404 self._params['page'], name, default, comment,
405 self._params["localedata"], html_escapes 405 self._params['localedata'], html_escapes
406 )) 406 ))
407 407
408 def get_string(self, name, page=None): 408 def get_string(self, name, page=None):
409 if page is None: 409 if page is None:
410 page = self._params["page"] 410 page = self._params['page']
411 411
412 localedata = self._params["source"].read_locale(self._params["locale"], page) 412 localedata = self._params['source'].read_locale(self._params['locale'], page)
413 default = localedata[name] 413 default = localedata[name]
414 return jinja2.Markup(self.localize_string( 414 return jinja2.Markup(self.localize_string(
415 page, name, default, "", localedata, html_escapes 415 page, name, default, '', localedata, html_escapes
416 )) 416 ))
417 417
418 def get_page_content(self, page, locale=None): 418 def get_page_content(self, page, locale=None):
419 from cms.utils import get_page_params 419 from cms.utils import get_page_params
420 420
421 if locale is None: 421 if locale is None:
422 locale = self._params["locale"] 422 locale = self._params['locale']
423 return get_page_params(self._params["source"], locale, page) 423 return get_page_params(self._params['source'], locale, page)
424 424
425 def linkify(self, page, locale=None, **attrs): 425 def linkify(self, page, locale=None, **attrs):
426 if locale is None: 426 if locale is None:
427 locale = self._params["locale"] 427 locale = self._params['locale']
428 428
429 locale, url = self._params["source"].resolve_link(page, locale) 429 locale, url = self._params['source'].resolve_link(page, locale)
430 return jinja2.Markup('<a%s>' % ''.join( 430 return jinja2.Markup('<a%s>' % ''.join(
431 ' %s="%s"' % (name, jinja2.escape(value)) for name, value in [ 431 ' %s="%s"' % (name, jinja2.escape(value)) for name, value in [
432 ('href', url), 432 ('href', url),
433 ('hreflang', locale) 433 ('hreflang', locale)
434 ] + attrs.items() 434 ] + attrs.items()
435 )) 435 ))
436 436
437 def toclist(self, content): 437 def toclist(self, content):
438 flat = [] 438 flat = []
439 for match in re.finditer(r'<h(\d)\s[^<>]*\bid="([^<>"]+)"[^<>]*>(.*?)</h \1>', content, re.S): 439 for match in re.finditer(r'<h(\d)\s[^<>]*\bid="([^<>"]+)"[^<>]*>(.*?)</h \1>', content, re.S):
440 flat.append({ 440 flat.append({
441 "level": int(match.group(1)), 441 'level': int(match.group(1)),
442 "anchor": jinja2.Markup(match.group(2)).unescape(), 442 'anchor': jinja2.Markup(match.group(2)).unescape(),
443 "title": jinja2.Markup(match.group(3)).unescape(), 443 'title': jinja2.Markup(match.group(3)).unescape(),
444 "subitems": [], 444 'subitems': [],
445 }) 445 })
446 446
447 structured = [] 447 structured = []
448 stack = [{"level": 0, "subitems": structured}] 448 stack = [{'level': 0, 'subitems': structured}]
449 for item in flat: 449 for item in flat:
450 while stack[-1]["level"] >= item["level"]: 450 while stack[-1]['level'] >= item['level']:
451 stack.pop() 451 stack.pop()
452 stack[-1]["subitems"].append(item) 452 stack[-1]['subitems'].append(item)
453 stack.append(item) 453 stack.append(item)
454 return structured 454 return structured
455 455
456 converters = { 456 converters = {
457 "html": RawConverter, 457 'html': RawConverter,
458 "md": MarkdownConverter, 458 'md': MarkdownConverter,
459 "tmpl": TemplateConverter, 459 'tmpl': TemplateConverter,
460 } 460 }
OLDNEW
« no previous file with comments | « cms/bin/translate.py ('k') | cms/sources.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld