##// END OF EJS Templates
templatefilters.json: stabilize output...
Gregory Szorc -
r23708:a9f826c3 default
parent child Browse files
Show More
@@ -1,421 +1,421 b''
1 # template-filters.py - common template expansion filters
1 # template-filters.py - common template expansion filters
2 #
2 #
3 # Copyright 2005-2008 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2008 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 import cgi, re, os, time, urllib
8 import cgi, re, os, time, urllib
9 import encoding, node, util
9 import encoding, node, util
10 import hbisect
10 import hbisect
11 import templatekw
11 import templatekw
12
12
13 def addbreaks(text):
13 def addbreaks(text):
14 """:addbreaks: Any text. Add an XHTML "<br />" tag before the end of
14 """:addbreaks: Any text. Add an XHTML "<br />" tag before the end of
15 every line except the last.
15 every line except the last.
16 """
16 """
17 return text.replace('\n', '<br/>\n')
17 return text.replace('\n', '<br/>\n')
18
18
19 agescales = [("year", 3600 * 24 * 365, 'Y'),
19 agescales = [("year", 3600 * 24 * 365, 'Y'),
20 ("month", 3600 * 24 * 30, 'M'),
20 ("month", 3600 * 24 * 30, 'M'),
21 ("week", 3600 * 24 * 7, 'W'),
21 ("week", 3600 * 24 * 7, 'W'),
22 ("day", 3600 * 24, 'd'),
22 ("day", 3600 * 24, 'd'),
23 ("hour", 3600, 'h'),
23 ("hour", 3600, 'h'),
24 ("minute", 60, 'm'),
24 ("minute", 60, 'm'),
25 ("second", 1, 's')]
25 ("second", 1, 's')]
26
26
27 def age(date, abbrev=False):
27 def age(date, abbrev=False):
28 """:age: Date. Returns a human-readable date/time difference between the
28 """:age: Date. Returns a human-readable date/time difference between the
29 given date/time and the current date/time.
29 given date/time and the current date/time.
30 """
30 """
31
31
32 def plural(t, c):
32 def plural(t, c):
33 if c == 1:
33 if c == 1:
34 return t
34 return t
35 return t + "s"
35 return t + "s"
36 def fmt(t, c, a):
36 def fmt(t, c, a):
37 if abbrev:
37 if abbrev:
38 return "%d%s" % (c, a)
38 return "%d%s" % (c, a)
39 return "%d %s" % (c, plural(t, c))
39 return "%d %s" % (c, plural(t, c))
40
40
41 now = time.time()
41 now = time.time()
42 then = date[0]
42 then = date[0]
43 future = False
43 future = False
44 if then > now:
44 if then > now:
45 future = True
45 future = True
46 delta = max(1, int(then - now))
46 delta = max(1, int(then - now))
47 if delta > agescales[0][1] * 30:
47 if delta > agescales[0][1] * 30:
48 return 'in the distant future'
48 return 'in the distant future'
49 else:
49 else:
50 delta = max(1, int(now - then))
50 delta = max(1, int(now - then))
51 if delta > agescales[0][1] * 2:
51 if delta > agescales[0][1] * 2:
52 return util.shortdate(date)
52 return util.shortdate(date)
53
53
54 for t, s, a in agescales:
54 for t, s, a in agescales:
55 n = delta // s
55 n = delta // s
56 if n >= 2 or s == 1:
56 if n >= 2 or s == 1:
57 if future:
57 if future:
58 return '%s from now' % fmt(t, n, a)
58 return '%s from now' % fmt(t, n, a)
59 return '%s ago' % fmt(t, n, a)
59 return '%s ago' % fmt(t, n, a)
60
60
61 def basename(path):
61 def basename(path):
62 """:basename: Any text. Treats the text as a path, and returns the last
62 """:basename: Any text. Treats the text as a path, and returns the last
63 component of the path after splitting by the path separator
63 component of the path after splitting by the path separator
64 (ignoring trailing separators). For example, "foo/bar/baz" becomes
64 (ignoring trailing separators). For example, "foo/bar/baz" becomes
65 "baz" and "foo/bar//" becomes "bar".
65 "baz" and "foo/bar//" becomes "bar".
66 """
66 """
67 return os.path.basename(path)
67 return os.path.basename(path)
68
68
69 def count(i):
69 def count(i):
70 """:count: List or text. Returns the length as an integer."""
70 """:count: List or text. Returns the length as an integer."""
71 return len(i)
71 return len(i)
72
72
73 def datefilter(text):
73 def datefilter(text):
74 """:date: Date. Returns a date in a Unix date format, including the
74 """:date: Date. Returns a date in a Unix date format, including the
75 timezone: "Mon Sep 04 15:13:13 2006 0700".
75 timezone: "Mon Sep 04 15:13:13 2006 0700".
76 """
76 """
77 return util.datestr(text)
77 return util.datestr(text)
78
78
79 def domain(author):
79 def domain(author):
80 """:domain: Any text. Finds the first string that looks like an email
80 """:domain: Any text. Finds the first string that looks like an email
81 address, and extracts just the domain component. Example: ``User
81 address, and extracts just the domain component. Example: ``User
82 <user@example.com>`` becomes ``example.com``.
82 <user@example.com>`` becomes ``example.com``.
83 """
83 """
84 f = author.find('@')
84 f = author.find('@')
85 if f == -1:
85 if f == -1:
86 return ''
86 return ''
87 author = author[f + 1:]
87 author = author[f + 1:]
88 f = author.find('>')
88 f = author.find('>')
89 if f >= 0:
89 if f >= 0:
90 author = author[:f]
90 author = author[:f]
91 return author
91 return author
92
92
93 def email(text):
93 def email(text):
94 """:email: Any text. Extracts the first string that looks like an email
94 """:email: Any text. Extracts the first string that looks like an email
95 address. Example: ``User <user@example.com>`` becomes
95 address. Example: ``User <user@example.com>`` becomes
96 ``user@example.com``.
96 ``user@example.com``.
97 """
97 """
98 return util.email(text)
98 return util.email(text)
99
99
100 def escape(text):
100 def escape(text):
101 """:escape: Any text. Replaces the special XML/XHTML characters "&", "<"
101 """:escape: Any text. Replaces the special XML/XHTML characters "&", "<"
102 and ">" with XML entities, and filters out NUL characters.
102 and ">" with XML entities, and filters out NUL characters.
103 """
103 """
104 return cgi.escape(text.replace('\0', ''), True)
104 return cgi.escape(text.replace('\0', ''), True)
105
105
106 para_re = None
106 para_re = None
107 space_re = None
107 space_re = None
108
108
109 def fill(text, width, initindent='', hangindent=''):
109 def fill(text, width, initindent='', hangindent=''):
110 '''fill many paragraphs with optional indentation.'''
110 '''fill many paragraphs with optional indentation.'''
111 global para_re, space_re
111 global para_re, space_re
112 if para_re is None:
112 if para_re is None:
113 para_re = re.compile('(\n\n|\n\\s*[-*]\\s*)', re.M)
113 para_re = re.compile('(\n\n|\n\\s*[-*]\\s*)', re.M)
114 space_re = re.compile(r' +')
114 space_re = re.compile(r' +')
115
115
116 def findparas():
116 def findparas():
117 start = 0
117 start = 0
118 while True:
118 while True:
119 m = para_re.search(text, start)
119 m = para_re.search(text, start)
120 if not m:
120 if not m:
121 uctext = unicode(text[start:], encoding.encoding)
121 uctext = unicode(text[start:], encoding.encoding)
122 w = len(uctext)
122 w = len(uctext)
123 while 0 < w and uctext[w - 1].isspace():
123 while 0 < w and uctext[w - 1].isspace():
124 w -= 1
124 w -= 1
125 yield (uctext[:w].encode(encoding.encoding),
125 yield (uctext[:w].encode(encoding.encoding),
126 uctext[w:].encode(encoding.encoding))
126 uctext[w:].encode(encoding.encoding))
127 break
127 break
128 yield text[start:m.start(0)], m.group(1)
128 yield text[start:m.start(0)], m.group(1)
129 start = m.end(1)
129 start = m.end(1)
130
130
131 return "".join([util.wrap(space_re.sub(' ', util.wrap(para, width)),
131 return "".join([util.wrap(space_re.sub(' ', util.wrap(para, width)),
132 width, initindent, hangindent) + rest
132 width, initindent, hangindent) + rest
133 for para, rest in findparas()])
133 for para, rest in findparas()])
134
134
135 def fill68(text):
135 def fill68(text):
136 """:fill68: Any text. Wraps the text to fit in 68 columns."""
136 """:fill68: Any text. Wraps the text to fit in 68 columns."""
137 return fill(text, 68)
137 return fill(text, 68)
138
138
139 def fill76(text):
139 def fill76(text):
140 """:fill76: Any text. Wraps the text to fit in 76 columns."""
140 """:fill76: Any text. Wraps the text to fit in 76 columns."""
141 return fill(text, 76)
141 return fill(text, 76)
142
142
143 def firstline(text):
143 def firstline(text):
144 """:firstline: Any text. Returns the first line of text."""
144 """:firstline: Any text. Returns the first line of text."""
145 try:
145 try:
146 return text.splitlines(True)[0].rstrip('\r\n')
146 return text.splitlines(True)[0].rstrip('\r\n')
147 except IndexError:
147 except IndexError:
148 return ''
148 return ''
149
149
150 def hexfilter(text):
150 def hexfilter(text):
151 """:hex: Any text. Convert a binary Mercurial node identifier into
151 """:hex: Any text. Convert a binary Mercurial node identifier into
152 its long hexadecimal representation.
152 its long hexadecimal representation.
153 """
153 """
154 return node.hex(text)
154 return node.hex(text)
155
155
156 def hgdate(text):
156 def hgdate(text):
157 """:hgdate: Date. Returns the date as a pair of numbers: "1157407993
157 """:hgdate: Date. Returns the date as a pair of numbers: "1157407993
158 25200" (Unix timestamp, timezone offset).
158 25200" (Unix timestamp, timezone offset).
159 """
159 """
160 return "%d %d" % text
160 return "%d %d" % text
161
161
162 def isodate(text):
162 def isodate(text):
163 """:isodate: Date. Returns the date in ISO 8601 format: "2009-08-18 13:00
163 """:isodate: Date. Returns the date in ISO 8601 format: "2009-08-18 13:00
164 +0200".
164 +0200".
165 """
165 """
166 return util.datestr(text, '%Y-%m-%d %H:%M %1%2')
166 return util.datestr(text, '%Y-%m-%d %H:%M %1%2')
167
167
168 def isodatesec(text):
168 def isodatesec(text):
169 """:isodatesec: Date. Returns the date in ISO 8601 format, including
169 """:isodatesec: Date. Returns the date in ISO 8601 format, including
170 seconds: "2009-08-18 13:00:13 +0200". See also the rfc3339date
170 seconds: "2009-08-18 13:00:13 +0200". See also the rfc3339date
171 filter.
171 filter.
172 """
172 """
173 return util.datestr(text, '%Y-%m-%d %H:%M:%S %1%2')
173 return util.datestr(text, '%Y-%m-%d %H:%M:%S %1%2')
174
174
175 def indent(text, prefix):
175 def indent(text, prefix):
176 '''indent each non-empty line of text after first with prefix.'''
176 '''indent each non-empty line of text after first with prefix.'''
177 lines = text.splitlines()
177 lines = text.splitlines()
178 num_lines = len(lines)
178 num_lines = len(lines)
179 endswithnewline = text[-1:] == '\n'
179 endswithnewline = text[-1:] == '\n'
180 def indenter():
180 def indenter():
181 for i in xrange(num_lines):
181 for i in xrange(num_lines):
182 l = lines[i]
182 l = lines[i]
183 if i and l.strip():
183 if i and l.strip():
184 yield prefix
184 yield prefix
185 yield l
185 yield l
186 if i < num_lines - 1 or endswithnewline:
186 if i < num_lines - 1 or endswithnewline:
187 yield '\n'
187 yield '\n'
188 return "".join(indenter())
188 return "".join(indenter())
189
189
190 def json(obj):
190 def json(obj):
191 if obj is None or obj is False or obj is True:
191 if obj is None or obj is False or obj is True:
192 return {None: 'null', False: 'false', True: 'true'}[obj]
192 return {None: 'null', False: 'false', True: 'true'}[obj]
193 elif isinstance(obj, int) or isinstance(obj, float):
193 elif isinstance(obj, int) or isinstance(obj, float):
194 return str(obj)
194 return str(obj)
195 elif isinstance(obj, str):
195 elif isinstance(obj, str):
196 u = unicode(obj, encoding.encoding, 'replace')
196 u = unicode(obj, encoding.encoding, 'replace')
197 return '"%s"' % jsonescape(u)
197 return '"%s"' % jsonescape(u)
198 elif isinstance(obj, unicode):
198 elif isinstance(obj, unicode):
199 return '"%s"' % jsonescape(obj)
199 return '"%s"' % jsonescape(obj)
200 elif util.safehasattr(obj, 'keys'):
200 elif util.safehasattr(obj, 'keys'):
201 out = []
201 out = []
202 for k, v in obj.iteritems():
202 for k, v in sorted(obj.iteritems()):
203 s = '%s: %s' % (json(k), json(v))
203 s = '%s: %s' % (json(k), json(v))
204 out.append(s)
204 out.append(s)
205 return '{' + ', '.join(out) + '}'
205 return '{' + ', '.join(out) + '}'
206 elif util.safehasattr(obj, '__iter__'):
206 elif util.safehasattr(obj, '__iter__'):
207 out = []
207 out = []
208 for i in obj:
208 for i in obj:
209 out.append(json(i))
209 out.append(json(i))
210 return '[' + ', '.join(out) + ']'
210 return '[' + ', '.join(out) + ']'
211 elif util.safehasattr(obj, '__call__'):
211 elif util.safehasattr(obj, '__call__'):
212 return json(obj())
212 return json(obj())
213 else:
213 else:
214 raise TypeError('cannot encode type %s' % obj.__class__.__name__)
214 raise TypeError('cannot encode type %s' % obj.__class__.__name__)
215
215
216 def _uescape(c):
216 def _uescape(c):
217 if ord(c) < 0x80:
217 if ord(c) < 0x80:
218 return c
218 return c
219 else:
219 else:
220 return '\\u%04x' % ord(c)
220 return '\\u%04x' % ord(c)
221
221
222 _escapes = [
222 _escapes = [
223 ('\\', '\\\\'), ('"', '\\"'), ('\t', '\\t'), ('\n', '\\n'),
223 ('\\', '\\\\'), ('"', '\\"'), ('\t', '\\t'), ('\n', '\\n'),
224 ('\r', '\\r'), ('\f', '\\f'), ('\b', '\\b'),
224 ('\r', '\\r'), ('\f', '\\f'), ('\b', '\\b'),
225 ('<', '\\u003c'), ('>', '\\u003e'), ('\0', '\\u0000')
225 ('<', '\\u003c'), ('>', '\\u003e'), ('\0', '\\u0000')
226 ]
226 ]
227
227
228 def jsonescape(s):
228 def jsonescape(s):
229 for k, v in _escapes:
229 for k, v in _escapes:
230 s = s.replace(k, v)
230 s = s.replace(k, v)
231 return ''.join(_uescape(c) for c in s)
231 return ''.join(_uescape(c) for c in s)
232
232
233 def localdate(text):
233 def localdate(text):
234 """:localdate: Date. Converts a date to local date."""
234 """:localdate: Date. Converts a date to local date."""
235 return (util.parsedate(text)[0], util.makedate()[1])
235 return (util.parsedate(text)[0], util.makedate()[1])
236
236
237 def nonempty(str):
237 def nonempty(str):
238 """:nonempty: Any text. Returns '(none)' if the string is empty."""
238 """:nonempty: Any text. Returns '(none)' if the string is empty."""
239 return str or "(none)"
239 return str or "(none)"
240
240
241 def obfuscate(text):
241 def obfuscate(text):
242 """:obfuscate: Any text. Returns the input text rendered as a sequence of
242 """:obfuscate: Any text. Returns the input text rendered as a sequence of
243 XML entities.
243 XML entities.
244 """
244 """
245 text = unicode(text, encoding.encoding, 'replace')
245 text = unicode(text, encoding.encoding, 'replace')
246 return ''.join(['&#%d;' % ord(c) for c in text])
246 return ''.join(['&#%d;' % ord(c) for c in text])
247
247
248 def permissions(flags):
248 def permissions(flags):
249 if "l" in flags:
249 if "l" in flags:
250 return "lrwxrwxrwx"
250 return "lrwxrwxrwx"
251 if "x" in flags:
251 if "x" in flags:
252 return "-rwxr-xr-x"
252 return "-rwxr-xr-x"
253 return "-rw-r--r--"
253 return "-rw-r--r--"
254
254
255 def person(author):
255 def person(author):
256 """:person: Any text. Returns the name before an email address,
256 """:person: Any text. Returns the name before an email address,
257 interpreting it as per RFC 5322.
257 interpreting it as per RFC 5322.
258
258
259 >>> person('foo@bar')
259 >>> person('foo@bar')
260 'foo'
260 'foo'
261 >>> person('Foo Bar <foo@bar>')
261 >>> person('Foo Bar <foo@bar>')
262 'Foo Bar'
262 'Foo Bar'
263 >>> person('"Foo Bar" <foo@bar>')
263 >>> person('"Foo Bar" <foo@bar>')
264 'Foo Bar'
264 'Foo Bar'
265 >>> person('"Foo \"buz\" Bar" <foo@bar>')
265 >>> person('"Foo \"buz\" Bar" <foo@bar>')
266 'Foo "buz" Bar'
266 'Foo "buz" Bar'
267 >>> # The following are invalid, but do exist in real-life
267 >>> # The following are invalid, but do exist in real-life
268 ...
268 ...
269 >>> person('Foo "buz" Bar <foo@bar>')
269 >>> person('Foo "buz" Bar <foo@bar>')
270 'Foo "buz" Bar'
270 'Foo "buz" Bar'
271 >>> person('"Foo Bar <foo@bar>')
271 >>> person('"Foo Bar <foo@bar>')
272 'Foo Bar'
272 'Foo Bar'
273 """
273 """
274 if '@' not in author:
274 if '@' not in author:
275 return author
275 return author
276 f = author.find('<')
276 f = author.find('<')
277 if f != -1:
277 if f != -1:
278 return author[:f].strip(' "').replace('\\"', '"')
278 return author[:f].strip(' "').replace('\\"', '"')
279 f = author.find('@')
279 f = author.find('@')
280 return author[:f].replace('.', ' ')
280 return author[:f].replace('.', ' ')
281
281
282 def rfc3339date(text):
282 def rfc3339date(text):
283 """:rfc3339date: Date. Returns a date using the Internet date format
283 """:rfc3339date: Date. Returns a date using the Internet date format
284 specified in RFC 3339: "2009-08-18T13:00:13+02:00".
284 specified in RFC 3339: "2009-08-18T13:00:13+02:00".
285 """
285 """
286 return util.datestr(text, "%Y-%m-%dT%H:%M:%S%1:%2")
286 return util.datestr(text, "%Y-%m-%dT%H:%M:%S%1:%2")
287
287
288 def rfc822date(text):
288 def rfc822date(text):
289 """:rfc822date: Date. Returns a date using the same format used in email
289 """:rfc822date: Date. Returns a date using the same format used in email
290 headers: "Tue, 18 Aug 2009 13:00:13 +0200".
290 headers: "Tue, 18 Aug 2009 13:00:13 +0200".
291 """
291 """
292 return util.datestr(text, "%a, %d %b %Y %H:%M:%S %1%2")
292 return util.datestr(text, "%a, %d %b %Y %H:%M:%S %1%2")
293
293
294 def short(text):
294 def short(text):
295 """:short: Changeset hash. Returns the short form of a changeset hash,
295 """:short: Changeset hash. Returns the short form of a changeset hash,
296 i.e. a 12 hexadecimal digit string.
296 i.e. a 12 hexadecimal digit string.
297 """
297 """
298 return text[:12]
298 return text[:12]
299
299
300 def shortbisect(text):
300 def shortbisect(text):
301 """:shortbisect: Any text. Treats `text` as a bisection status, and
301 """:shortbisect: Any text. Treats `text` as a bisection status, and
302 returns a single-character representing the status (G: good, B: bad,
302 returns a single-character representing the status (G: good, B: bad,
303 S: skipped, U: untested, I: ignored). Returns single space if `text`
303 S: skipped, U: untested, I: ignored). Returns single space if `text`
304 is not a valid bisection status.
304 is not a valid bisection status.
305 """
305 """
306 return hbisect.shortlabel(text) or ' '
306 return hbisect.shortlabel(text) or ' '
307
307
308 def shortdate(text):
308 def shortdate(text):
309 """:shortdate: Date. Returns a date like "2006-09-18"."""
309 """:shortdate: Date. Returns a date like "2006-09-18"."""
310 return util.shortdate(text)
310 return util.shortdate(text)
311
311
312 def splitlines(text):
312 def splitlines(text):
313 """:splitlines: Any text. Split text into a list of lines."""
313 """:splitlines: Any text. Split text into a list of lines."""
314 return templatekw.showlist('line', text.splitlines(), 'lines')
314 return templatekw.showlist('line', text.splitlines(), 'lines')
315
315
316 def stringescape(text):
316 def stringescape(text):
317 return text.encode('string_escape')
317 return text.encode('string_escape')
318
318
319 def stringify(thing):
319 def stringify(thing):
320 """:stringify: Any type. Turns the value into text by converting values into
320 """:stringify: Any type. Turns the value into text by converting values into
321 text and concatenating them.
321 text and concatenating them.
322 """
322 """
323 if util.safehasattr(thing, '__iter__') and not isinstance(thing, str):
323 if util.safehasattr(thing, '__iter__') and not isinstance(thing, str):
324 return "".join([stringify(t) for t in thing if t is not None])
324 return "".join([stringify(t) for t in thing if t is not None])
325 return str(thing)
325 return str(thing)
326
326
327 def strip(text):
327 def strip(text):
328 """:strip: Any text. Strips all leading and trailing whitespace."""
328 """:strip: Any text. Strips all leading and trailing whitespace."""
329 return text.strip()
329 return text.strip()
330
330
331 def stripdir(text):
331 def stripdir(text):
332 """:stripdir: Treat the text as path and strip a directory level, if
332 """:stripdir: Treat the text as path and strip a directory level, if
333 possible. For example, "foo" and "foo/bar" becomes "foo".
333 possible. For example, "foo" and "foo/bar" becomes "foo".
334 """
334 """
335 dir = os.path.dirname(text)
335 dir = os.path.dirname(text)
336 if dir == "":
336 if dir == "":
337 return os.path.basename(text)
337 return os.path.basename(text)
338 else:
338 else:
339 return dir
339 return dir
340
340
341 def tabindent(text):
341 def tabindent(text):
342 """:tabindent: Any text. Returns the text, with every non-empty line
342 """:tabindent: Any text. Returns the text, with every non-empty line
343 except the first starting with a tab character.
343 except the first starting with a tab character.
344 """
344 """
345 return indent(text, '\t')
345 return indent(text, '\t')
346
346
347 def urlescape(text):
347 def urlescape(text):
348 """:urlescape: Any text. Escapes all "special" characters. For example,
348 """:urlescape: Any text. Escapes all "special" characters. For example,
349 "foo bar" becomes "foo%20bar".
349 "foo bar" becomes "foo%20bar".
350 """
350 """
351 return urllib.quote(text)
351 return urllib.quote(text)
352
352
353 def userfilter(text):
353 def userfilter(text):
354 """:user: Any text. Returns a short representation of a user name or email
354 """:user: Any text. Returns a short representation of a user name or email
355 address."""
355 address."""
356 return util.shortuser(text)
356 return util.shortuser(text)
357
357
358 def emailuser(text):
358 def emailuser(text):
359 """:emailuser: Any text. Returns the user portion of an email address."""
359 """:emailuser: Any text. Returns the user portion of an email address."""
360 return util.emailuser(text)
360 return util.emailuser(text)
361
361
362 def xmlescape(text):
362 def xmlescape(text):
363 text = (text
363 text = (text
364 .replace('&', '&amp;')
364 .replace('&', '&amp;')
365 .replace('<', '&lt;')
365 .replace('<', '&lt;')
366 .replace('>', '&gt;')
366 .replace('>', '&gt;')
367 .replace('"', '&quot;')
367 .replace('"', '&quot;')
368 .replace("'", '&#39;')) # &apos; invalid in HTML
368 .replace("'", '&#39;')) # &apos; invalid in HTML
369 return re.sub('[\x00-\x08\x0B\x0C\x0E-\x1F]', ' ', text)
369 return re.sub('[\x00-\x08\x0B\x0C\x0E-\x1F]', ' ', text)
370
370
371 filters = {
371 filters = {
372 "addbreaks": addbreaks,
372 "addbreaks": addbreaks,
373 "age": age,
373 "age": age,
374 "basename": basename,
374 "basename": basename,
375 "count": count,
375 "count": count,
376 "date": datefilter,
376 "date": datefilter,
377 "domain": domain,
377 "domain": domain,
378 "email": email,
378 "email": email,
379 "escape": escape,
379 "escape": escape,
380 "fill68": fill68,
380 "fill68": fill68,
381 "fill76": fill76,
381 "fill76": fill76,
382 "firstline": firstline,
382 "firstline": firstline,
383 "hex": hexfilter,
383 "hex": hexfilter,
384 "hgdate": hgdate,
384 "hgdate": hgdate,
385 "isodate": isodate,
385 "isodate": isodate,
386 "isodatesec": isodatesec,
386 "isodatesec": isodatesec,
387 "json": json,
387 "json": json,
388 "jsonescape": jsonescape,
388 "jsonescape": jsonescape,
389 "localdate": localdate,
389 "localdate": localdate,
390 "nonempty": nonempty,
390 "nonempty": nonempty,
391 "obfuscate": obfuscate,
391 "obfuscate": obfuscate,
392 "permissions": permissions,
392 "permissions": permissions,
393 "person": person,
393 "person": person,
394 "rfc3339date": rfc3339date,
394 "rfc3339date": rfc3339date,
395 "rfc822date": rfc822date,
395 "rfc822date": rfc822date,
396 "short": short,
396 "short": short,
397 "shortbisect": shortbisect,
397 "shortbisect": shortbisect,
398 "shortdate": shortdate,
398 "shortdate": shortdate,
399 "splitlines": splitlines,
399 "splitlines": splitlines,
400 "stringescape": stringescape,
400 "stringescape": stringescape,
401 "stringify": stringify,
401 "stringify": stringify,
402 "strip": strip,
402 "strip": strip,
403 "stripdir": stripdir,
403 "stripdir": stripdir,
404 "tabindent": tabindent,
404 "tabindent": tabindent,
405 "urlescape": urlescape,
405 "urlescape": urlescape,
406 "user": userfilter,
406 "user": userfilter,
407 "emailuser": emailuser,
407 "emailuser": emailuser,
408 "xmlescape": xmlescape,
408 "xmlescape": xmlescape,
409 }
409 }
410
410
411 def websub(text, websubtable):
411 def websub(text, websubtable):
412 """:websub: Any text. Only applies to hgweb. Applies the regular
412 """:websub: Any text. Only applies to hgweb. Applies the regular
413 expression replacements defined in the websub section.
413 expression replacements defined in the websub section.
414 """
414 """
415 if websubtable:
415 if websubtable:
416 for regexp, format in websubtable:
416 for regexp, format in websubtable:
417 text = regexp.sub(format, text)
417 text = regexp.sub(format, text)
418 return text
418 return text
419
419
420 # tell hggettext to extract docstrings from these functions:
420 # tell hggettext to extract docstrings from these functions:
421 i18nfunctions = filters.values()
421 i18nfunctions = filters.values()
General Comments 0
You need to be logged in to leave comments. Login now