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