##// END OF EJS Templates
templatefilters.json: call functions...
Gregory Szorc -
r23707:ae5447de default
parent child Browse files
Show More
@@ -1,419 +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 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__'):
212 return json(obj())
211 else:
213 else:
212 raise TypeError('cannot encode type %s' % obj.__class__.__name__)
214 raise TypeError('cannot encode type %s' % obj.__class__.__name__)
213
215
214 def _uescape(c):
216 def _uescape(c):
215 if ord(c) < 0x80:
217 if ord(c) < 0x80:
216 return c
218 return c
217 else:
219 else:
218 return '\\u%04x' % ord(c)
220 return '\\u%04x' % ord(c)
219
221
220 _escapes = [
222 _escapes = [
221 ('\\', '\\\\'), ('"', '\\"'), ('\t', '\\t'), ('\n', '\\n'),
223 ('\\', '\\\\'), ('"', '\\"'), ('\t', '\\t'), ('\n', '\\n'),
222 ('\r', '\\r'), ('\f', '\\f'), ('\b', '\\b'),
224 ('\r', '\\r'), ('\f', '\\f'), ('\b', '\\b'),
223 ('<', '\\u003c'), ('>', '\\u003e'), ('\0', '\\u0000')
225 ('<', '\\u003c'), ('>', '\\u003e'), ('\0', '\\u0000')
224 ]
226 ]
225
227
226 def jsonescape(s):
228 def jsonescape(s):
227 for k, v in _escapes:
229 for k, v in _escapes:
228 s = s.replace(k, v)
230 s = s.replace(k, v)
229 return ''.join(_uescape(c) for c in s)
231 return ''.join(_uescape(c) for c in s)
230
232
231 def localdate(text):
233 def localdate(text):
232 """:localdate: Date. Converts a date to local date."""
234 """:localdate: Date. Converts a date to local date."""
233 return (util.parsedate(text)[0], util.makedate()[1])
235 return (util.parsedate(text)[0], util.makedate()[1])
234
236
235 def nonempty(str):
237 def nonempty(str):
236 """:nonempty: Any text. Returns '(none)' if the string is empty."""
238 """:nonempty: Any text. Returns '(none)' if the string is empty."""
237 return str or "(none)"
239 return str or "(none)"
238
240
239 def obfuscate(text):
241 def obfuscate(text):
240 """: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
241 XML entities.
243 XML entities.
242 """
244 """
243 text = unicode(text, encoding.encoding, 'replace')
245 text = unicode(text, encoding.encoding, 'replace')
244 return ''.join(['&#%d;' % ord(c) for c in text])
246 return ''.join(['&#%d;' % ord(c) for c in text])
245
247
246 def permissions(flags):
248 def permissions(flags):
247 if "l" in flags:
249 if "l" in flags:
248 return "lrwxrwxrwx"
250 return "lrwxrwxrwx"
249 if "x" in flags:
251 if "x" in flags:
250 return "-rwxr-xr-x"
252 return "-rwxr-xr-x"
251 return "-rw-r--r--"
253 return "-rw-r--r--"
252
254
253 def person(author):
255 def person(author):
254 """:person: Any text. Returns the name before an email address,
256 """:person: Any text. Returns the name before an email address,
255 interpreting it as per RFC 5322.
257 interpreting it as per RFC 5322.
256
258
257 >>> person('foo@bar')
259 >>> person('foo@bar')
258 'foo'
260 'foo'
259 >>> person('Foo Bar <foo@bar>')
261 >>> person('Foo Bar <foo@bar>')
260 'Foo Bar'
262 'Foo Bar'
261 >>> person('"Foo Bar" <foo@bar>')
263 >>> person('"Foo Bar" <foo@bar>')
262 'Foo Bar'
264 'Foo Bar'
263 >>> person('"Foo \"buz\" Bar" <foo@bar>')
265 >>> person('"Foo \"buz\" Bar" <foo@bar>')
264 'Foo "buz" Bar'
266 'Foo "buz" Bar'
265 >>> # The following are invalid, but do exist in real-life
267 >>> # The following are invalid, but do exist in real-life
266 ...
268 ...
267 >>> person('Foo "buz" Bar <foo@bar>')
269 >>> person('Foo "buz" Bar <foo@bar>')
268 'Foo "buz" Bar'
270 'Foo "buz" Bar'
269 >>> person('"Foo Bar <foo@bar>')
271 >>> person('"Foo Bar <foo@bar>')
270 'Foo Bar'
272 'Foo Bar'
271 """
273 """
272 if '@' not in author:
274 if '@' not in author:
273 return author
275 return author
274 f = author.find('<')
276 f = author.find('<')
275 if f != -1:
277 if f != -1:
276 return author[:f].strip(' "').replace('\\"', '"')
278 return author[:f].strip(' "').replace('\\"', '"')
277 f = author.find('@')
279 f = author.find('@')
278 return author[:f].replace('.', ' ')
280 return author[:f].replace('.', ' ')
279
281
280 def rfc3339date(text):
282 def rfc3339date(text):
281 """:rfc3339date: Date. Returns a date using the Internet date format
283 """:rfc3339date: Date. Returns a date using the Internet date format
282 specified in RFC 3339: "2009-08-18T13:00:13+02:00".
284 specified in RFC 3339: "2009-08-18T13:00:13+02:00".
283 """
285 """
284 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")
285
287
286 def rfc822date(text):
288 def rfc822date(text):
287 """: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
288 headers: "Tue, 18 Aug 2009 13:00:13 +0200".
290 headers: "Tue, 18 Aug 2009 13:00:13 +0200".
289 """
291 """
290 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")
291
293
292 def short(text):
294 def short(text):
293 """:short: Changeset hash. Returns the short form of a changeset hash,
295 """:short: Changeset hash. Returns the short form of a changeset hash,
294 i.e. a 12 hexadecimal digit string.
296 i.e. a 12 hexadecimal digit string.
295 """
297 """
296 return text[:12]
298 return text[:12]
297
299
298 def shortbisect(text):
300 def shortbisect(text):
299 """:shortbisect: Any text. Treats `text` as a bisection status, and
301 """:shortbisect: Any text. Treats `text` as a bisection status, and
300 returns a single-character representing the status (G: good, B: bad,
302 returns a single-character representing the status (G: good, B: bad,
301 S: skipped, U: untested, I: ignored). Returns single space if `text`
303 S: skipped, U: untested, I: ignored). Returns single space if `text`
302 is not a valid bisection status.
304 is not a valid bisection status.
303 """
305 """
304 return hbisect.shortlabel(text) or ' '
306 return hbisect.shortlabel(text) or ' '
305
307
306 def shortdate(text):
308 def shortdate(text):
307 """:shortdate: Date. Returns a date like "2006-09-18"."""
309 """:shortdate: Date. Returns a date like "2006-09-18"."""
308 return util.shortdate(text)
310 return util.shortdate(text)
309
311
310 def splitlines(text):
312 def splitlines(text):
311 """:splitlines: Any text. Split text into a list of lines."""
313 """:splitlines: Any text. Split text into a list of lines."""
312 return templatekw.showlist('line', text.splitlines(), 'lines')
314 return templatekw.showlist('line', text.splitlines(), 'lines')
313
315
314 def stringescape(text):
316 def stringescape(text):
315 return text.encode('string_escape')
317 return text.encode('string_escape')
316
318
317 def stringify(thing):
319 def stringify(thing):
318 """: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
319 text and concatenating them.
321 text and concatenating them.
320 """
322 """
321 if util.safehasattr(thing, '__iter__') and not isinstance(thing, str):
323 if util.safehasattr(thing, '__iter__') and not isinstance(thing, str):
322 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])
323 return str(thing)
325 return str(thing)
324
326
325 def strip(text):
327 def strip(text):
326 """:strip: Any text. Strips all leading and trailing whitespace."""
328 """:strip: Any text. Strips all leading and trailing whitespace."""
327 return text.strip()
329 return text.strip()
328
330
329 def stripdir(text):
331 def stripdir(text):
330 """: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
331 possible. For example, "foo" and "foo/bar" becomes "foo".
333 possible. For example, "foo" and "foo/bar" becomes "foo".
332 """
334 """
333 dir = os.path.dirname(text)
335 dir = os.path.dirname(text)
334 if dir == "":
336 if dir == "":
335 return os.path.basename(text)
337 return os.path.basename(text)
336 else:
338 else:
337 return dir
339 return dir
338
340
339 def tabindent(text):
341 def tabindent(text):
340 """:tabindent: Any text. Returns the text, with every non-empty line
342 """:tabindent: Any text. Returns the text, with every non-empty line
341 except the first starting with a tab character.
343 except the first starting with a tab character.
342 """
344 """
343 return indent(text, '\t')
345 return indent(text, '\t')
344
346
345 def urlescape(text):
347 def urlescape(text):
346 """:urlescape: Any text. Escapes all "special" characters. For example,
348 """:urlescape: Any text. Escapes all "special" characters. For example,
347 "foo bar" becomes "foo%20bar".
349 "foo bar" becomes "foo%20bar".
348 """
350 """
349 return urllib.quote(text)
351 return urllib.quote(text)
350
352
351 def userfilter(text):
353 def userfilter(text):
352 """: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
353 address."""
355 address."""
354 return util.shortuser(text)
356 return util.shortuser(text)
355
357
356 def emailuser(text):
358 def emailuser(text):
357 """:emailuser: Any text. Returns the user portion of an email address."""
359 """:emailuser: Any text. Returns the user portion of an email address."""
358 return util.emailuser(text)
360 return util.emailuser(text)
359
361
360 def xmlescape(text):
362 def xmlescape(text):
361 text = (text
363 text = (text
362 .replace('&', '&amp;')
364 .replace('&', '&amp;')
363 .replace('<', '&lt;')
365 .replace('<', '&lt;')
364 .replace('>', '&gt;')
366 .replace('>', '&gt;')
365 .replace('"', '&quot;')
367 .replace('"', '&quot;')
366 .replace("'", '&#39;')) # &apos; invalid in HTML
368 .replace("'", '&#39;')) # &apos; invalid in HTML
367 return re.sub('[\x00-\x08\x0B\x0C\x0E-\x1F]', ' ', text)
369 return re.sub('[\x00-\x08\x0B\x0C\x0E-\x1F]', ' ', text)
368
370
369 filters = {
371 filters = {
370 "addbreaks": addbreaks,
372 "addbreaks": addbreaks,
371 "age": age,
373 "age": age,
372 "basename": basename,
374 "basename": basename,
373 "count": count,
375 "count": count,
374 "date": datefilter,
376 "date": datefilter,
375 "domain": domain,
377 "domain": domain,
376 "email": email,
378 "email": email,
377 "escape": escape,
379 "escape": escape,
378 "fill68": fill68,
380 "fill68": fill68,
379 "fill76": fill76,
381 "fill76": fill76,
380 "firstline": firstline,
382 "firstline": firstline,
381 "hex": hexfilter,
383 "hex": hexfilter,
382 "hgdate": hgdate,
384 "hgdate": hgdate,
383 "isodate": isodate,
385 "isodate": isodate,
384 "isodatesec": isodatesec,
386 "isodatesec": isodatesec,
385 "json": json,
387 "json": json,
386 "jsonescape": jsonescape,
388 "jsonescape": jsonescape,
387 "localdate": localdate,
389 "localdate": localdate,
388 "nonempty": nonempty,
390 "nonempty": nonempty,
389 "obfuscate": obfuscate,
391 "obfuscate": obfuscate,
390 "permissions": permissions,
392 "permissions": permissions,
391 "person": person,
393 "person": person,
392 "rfc3339date": rfc3339date,
394 "rfc3339date": rfc3339date,
393 "rfc822date": rfc822date,
395 "rfc822date": rfc822date,
394 "short": short,
396 "short": short,
395 "shortbisect": shortbisect,
397 "shortbisect": shortbisect,
396 "shortdate": shortdate,
398 "shortdate": shortdate,
397 "splitlines": splitlines,
399 "splitlines": splitlines,
398 "stringescape": stringescape,
400 "stringescape": stringescape,
399 "stringify": stringify,
401 "stringify": stringify,
400 "strip": strip,
402 "strip": strip,
401 "stripdir": stripdir,
403 "stripdir": stripdir,
402 "tabindent": tabindent,
404 "tabindent": tabindent,
403 "urlescape": urlescape,
405 "urlescape": urlescape,
404 "user": userfilter,
406 "user": userfilter,
405 "emailuser": emailuser,
407 "emailuser": emailuser,
406 "xmlescape": xmlescape,
408 "xmlescape": xmlescape,
407 }
409 }
408
410
409 def websub(text, websubtable):
411 def websub(text, websubtable):
410 """:websub: Any text. Only applies to hgweb. Applies the regular
412 """:websub: Any text. Only applies to hgweb. Applies the regular
411 expression replacements defined in the websub section.
413 expression replacements defined in the websub section.
412 """
414 """
413 if websubtable:
415 if websubtable:
414 for regexp, format in websubtable:
416 for regexp, format in websubtable:
415 text = regexp.sub(format, text)
417 text = regexp.sub(format, text)
416 return text
418 return text
417
419
418 # tell hggettext to extract docstrings from these functions:
420 # tell hggettext to extract docstrings from these functions:
419 i18nfunctions = filters.values()
421 i18nfunctions = filters.values()
General Comments 0
You need to be logged in to leave comments. Login now