##// END OF EJS Templates
repoview: do not crash when localtags refers to non existing revisions...
repoview: do not crash when localtags refers to non existing revisions This fixes a crash that may happen when using mercurial 3.0.x. The _gethiddenblockers function assumed that the output of tags.readlocaltags() was a dict mapping tags to of valid nodes. However this was not necessarily the case. When a repository had obsolete revisions and had local tag pointing to a non existing revision was found, many mercurial commands would crash. This revision fixes the problem by removing any tags from the output of tags.readlocaltags() which point to invalid nodes. We may want to add a warning when this happens (although it might be annoying to get that warning for every command, possibly even more than once per command). A test for this problem has been added to test-obsolete.t. Without this fix the test would output: $ hg tags abort: 00changelog.i@3816541e5485: no node! [255] Instead of: $ hg tags tiptag 2:3816541e5485 tip 2:3816541e5485 visible 0:193e9254ce7e

File last commit:

r21820:cce404b0 default
r21823:925d1bb9 stable
Show More
templatefilters.py
408 lines | 12.1 KiB | text/x-python | PythonLexer
Matt Mackall
templates: move filters to their own module...
r5976 # template-filters.py - common template expansion filters
#
# Copyright 2005-2008 Matt Mackall <mpm@selenic.com>
#
Martin Geisler
updated license to be explicit about GPL version 2
r8225 # This software may be used and distributed according to the terms of the
Matt Mackall
Update license to GPLv2+
r10263 # GNU General Public License version 2 or any later version.
Matt Mackall
templates: move filters to their own module...
r5976
FUJIWARA Katsunori
replace Python standard textwrap by MBCS sensitive one for i18n text...
r11297 import cgi, re, os, time, urllib
Sean Farley
templater: move templatefilters.func into the same place as the other funcs
r19227 import encoding, node, util
"Yann E. MORIN"
templates: add 'bisect' keyword to return a cset's bisect status...
r15155 import hbisect
Matt Mackall
templates: move filters to their own module...
r5976
Patrick Mezard
templatefilters: sort function definitions
r13588 def addbreaks(text):
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 """:addbreaks: Any text. Add an XHTML "<br />" tag before the end of
every line except the last.
"""
Patrick Mezard
templatefilters: sort function definitions
r13588 return text.replace('\n', '<br/>\n')
Dirkjan Ochtman
templater: provide the standard template filters by default
r8360
David Soria Parra
templatefilters: add short format for age formatting...
r19736 agescales = [("year", 3600 * 24 * 365, 'Y'),
("month", 3600 * 24 * 30, 'M'),
("week", 3600 * 24 * 7, 'W'),
("day", 3600 * 24, 'd'),
("hour", 3600, 'h'),
("minute", 60, 'm'),
("second", 1, 's')]
Matt Mackall
templates: move filters to their own module...
r5976
David Soria Parra
templatefilters: add short format for age formatting...
r19736 def age(date, abbrev=False):
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 """:age: Date. Returns a human-readable date/time difference between the
given date/time and the current date/time.
"""
Matt Mackall
templates: move filters to their own module...
r5976
def plural(t, c):
if c == 1:
return t
return t + "s"
David Soria Parra
templatefilters: add short format for age formatting...
r19736 def fmt(t, c, a):
if abbrev:
return "%d%s" % (c, a)
Matt Mackall
templates: move filters to their own module...
r5976 return "%d %s" % (c, plural(t, c))
now = time.time()
then = date[0]
timeless
templates: provide granularity for future values for age filter
r13666 future = False
Dirkjan Ochtman
templater: fix age filter to state the obvious on future timestamps
r7682 if then > now:
timeless
templates: provide granularity for future values for age filter
r13666 future = True
delta = max(1, int(then - now))
if delta > agescales[0][1] * 30:
return 'in the distant future'
else:
delta = max(1, int(now - then))
if delta > agescales[0][1] * 2:
return util.shortdate(date)
Dirkjan Ochtman
templater: readable dates older than 24 months revert to ISO8601 (issue1006)
r9722
David Soria Parra
templatefilters: add short format for age formatting...
r19736 for t, s, a in agescales:
Alejandro Santos
compat: use // for integer division
r9029 n = delta // s
Matt Mackall
templates: move filters to their own module...
r5976 if n >= 2 or s == 1:
timeless
templates: provide granularity for future values for age filter
r13666 if future:
David Soria Parra
templatefilters: add short format for age formatting...
r19736 return '%s from now' % fmt(t, n, a)
return '%s ago' % fmt(t, n, a)
Matt Mackall
templates: move filters to their own module...
r5976
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 def basename(path):
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 """:basename: Any text. Treats the text as a path, and returns the last
component of the path after splitting by the path separator
(ignoring trailing separators). For example, "foo/bar/baz" becomes
"baz" and "foo/bar//" becomes "bar".
"""
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 return os.path.basename(path)
def datefilter(text):
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 """:date: Date. Returns a date in a Unix date format, including the
timezone: "Mon Sep 04 15:13:13 2006 0700".
"""
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 return util.datestr(text)
Patrick Mezard
templatefilters: sort function definitions
r13588 def domain(author):
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 """:domain: Any text. Finds the first string that looks like an email
address, and extracts just the domain component. Example: ``User
<user@example.com>`` becomes ``example.com``.
"""
Patrick Mezard
templatefilters: sort function definitions
r13588 f = author.find('@')
if f == -1:
return ''
author = author[f + 1:]
f = author.find('>')
if f >= 0:
author = author[:f]
return author
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 def email(text):
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 """:email: Any text. Extracts the first string that looks like an email
address. Example: ``User <user@example.com>`` becomes
``user@example.com``.
"""
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 return util.email(text)
def escape(text):
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 """:escape: Any text. Replaces the special XML/XHTML characters "&", "<"
Siddharth Agarwal
hgweb: make the escape filter remove null characters (issue2567)
r17772 and ">" with XML entities, and filters out NUL characters.
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 """
Siddharth Agarwal
hgweb: make the escape filter remove null characters (issue2567)
r17772 return cgi.escape(text.replace('\0', ''), True)
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590
Matt Mackall
templates: move filters to their own module...
r5976 para_re = None
space_re = None
Mads Kiilerich
check-code: check for spaces around = for named parameters
r19872 def fill(text, width, initindent='', hangindent=''):
Sean Farley
templater: add indentation arguments to the fill function
r19228 '''fill many paragraphs with optional indentation.'''
Matt Mackall
templates: move filters to their own module...
r5976 global para_re, space_re
if para_re is None:
para_re = re.compile('(\n\n|\n\\s*[-*]\\s*)', re.M)
space_re = re.compile(r' +')
def findparas():
start = 0
while True:
m = para_re.search(text, start)
if not m:
FUJIWARA Katsunori
replace Python standard textwrap by MBCS sensitive one for i18n text...
r11297 uctext = unicode(text[start:], encoding.encoding)
w = len(uctext)
while 0 < w and uctext[w - 1].isspace():
Matt Mackall
many, many trivial check-code fixups
r10282 w -= 1
FUJIWARA Katsunori
replace Python standard textwrap by MBCS sensitive one for i18n text...
r11297 yield (uctext[:w].encode(encoding.encoding),
uctext[w:].encode(encoding.encoding))
Matt Mackall
templates: move filters to their own module...
r5976 break
yield text[start:m.start(0)], m.group(1)
start = m.end(1)
Sean Farley
templater: add indentation arguments to the fill function
r19228 return "".join([util.wrap(space_re.sub(' ', util.wrap(para, width)),
width, initindent, hangindent) + rest
Matt Mackall
templates: move filters to their own module...
r5976 for para, rest in findparas()])
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 def fill68(text):
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 """:fill68: Any text. Wraps the text to fit in 68 columns."""
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 return fill(text, 68)
def fill76(text):
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 """:fill76: Any text. Wraps the text to fit in 76 columns."""
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 return fill(text, 76)
Matt Mackall
templates: move filters to their own module...
r5976 def firstline(text):
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 """:firstline: Any text. Returns the first line of text."""
Matt Mackall
templates: move filters to their own module...
r5976 try:
Nicolas Dumazet
for calls expecting bool args, pass bool instead of int...
r9136 return text.splitlines(True)[0].rstrip('\r\n')
Matt Mackall
templates: move filters to their own module...
r5976 except IndexError:
return ''
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 def hexfilter(text):
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 """:hex: Any text. Convert a binary Mercurial node identifier into
its long hexadecimal representation.
"""
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 return node.hex(text)
def hgdate(text):
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 """:hgdate: Date. Returns the date as a pair of numbers: "1157407993
25200" (Unix timestamp, timezone offset).
"""
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 return "%d %d" % text
def isodate(text):
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 """:isodate: Date. Returns the date in ISO 8601 format: "2009-08-18 13:00
+0200".
"""
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 return util.datestr(text, '%Y-%m-%d %H:%M %1%2')
def isodatesec(text):
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 """:isodatesec: Date. Returns the date in ISO 8601 format, including
seconds: "2009-08-18 13:00:13 +0200". See also the rfc3339date
filter.
"""
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 return util.datestr(text, '%Y-%m-%d %H:%M:%S %1%2')
Matt Mackall
templates: move filters to their own module...
r5976 def indent(text, prefix):
'''indent each non-empty line of text after first with prefix.'''
lines = text.splitlines()
num_lines = len(lines)
Nicolas Dumazet
templatefilters: indent: do not compute text.endswith('\n') in each iteration
r9387 endswithnewline = text[-1:] == '\n'
Matt Mackall
templates: move filters to their own module...
r5976 def indenter():
for i in xrange(num_lines):
l = lines[i]
if i and l.strip():
yield prefix
yield l
Nicolas Dumazet
templatefilters: indent: do not compute text.endswith('\n') in each iteration
r9387 if i < num_lines - 1 or endswithnewline:
Matt Mackall
templates: move filters to their own module...
r5976 yield '\n'
return "".join(indenter())
Dirkjan Ochtman
add graph page to hgweb
r6691 def json(obj):
if obj is None or obj is False or obj is True:
return {None: 'null', False: 'false', True: 'true'}[obj]
elif isinstance(obj, int) or isinstance(obj, float):
return str(obj)
elif isinstance(obj, str):
Yuya Nishihara
templatefilters: make json filter handle multibyte characters correctly...
r11765 u = unicode(obj, encoding.encoding, 'replace')
Yuya Nishihara
templatefilters: use \uxxxx style escape for JSON string...
r11890 return '"%s"' % jsonescape(u)
Dirkjan Ochtman
add graph page to hgweb
r6691 elif isinstance(obj, unicode):
Yuya Nishihara
templatefilters: use \uxxxx style escape for JSON string...
r11890 return '"%s"' % jsonescape(obj)
Augie Fackler
templatefilters: use safehasattr instead of hasattr
r14967 elif util.safehasattr(obj, 'keys'):
Dirkjan Ochtman
add graph page to hgweb
r6691 out = []
for k, v in obj.iteritems():
s = '%s: %s' % (json(k), json(v))
out.append(s)
return '{' + ', '.join(out) + '}'
Augie Fackler
globally: use safehasattr(x, '__iter__') instead of hasattr(x, '__iter__')
r14944 elif util.safehasattr(obj, '__iter__'):
Dirkjan Ochtman
add graph page to hgweb
r6691 out = []
for i in obj:
out.append(json(i))
return '[' + ', '.join(out) + ']'
else:
raise TypeError('cannot encode type %s' % obj.__class__.__name__)
Patrick Mezard
templatefilters: prefix helper functions
r13589 def _uescape(c):
Patrick Mezard
templatefilters: sort function definitions
r13588 if ord(c) < 0x80:
return c
else:
return '\\u%04x' % ord(c)
_escapes = [
('\\', '\\\\'), ('"', '\\"'), ('\t', '\\t'), ('\n', '\\n'),
('\r', '\\r'), ('\f', '\\f'), ('\b', '\\b'),
Matt Mackall
json: add more paranoid escaping
r19882 ('<', '\\u003c'), ('>', '\\u003e')
Patrick Mezard
templatefilters: sort function definitions
r13588 ]
def jsonescape(s):
for k, v in _escapes:
s = s.replace(k, v)
Patrick Mezard
templatefilters: prefix helper functions
r13589 return ''.join(_uescape(c) for c in s)
Patrick Mezard
templatefilters: sort function definitions
r13588
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 def localdate(text):
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 """:localdate: Date. Converts a date to local date."""
Christian Ebert
templatefilters: avoid traceback caused by bogus date input (issue3344)...
r17755 return (util.parsedate(text)[0], util.makedate()[1])
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590
Patrick Mezard
templatefilters: sort function definitions
r13588 def nonempty(str):
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 """:nonempty: Any text. Returns '(none)' if the string is empty."""
Patrick Mezard
templatefilters: sort function definitions
r13588 return str or "(none)"
def obfuscate(text):
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 """:obfuscate: Any text. Returns the input text rendered as a sequence of
XML entities.
"""
Patrick Mezard
templatefilters: sort function definitions
r13588 text = unicode(text, encoding.encoding, 'replace')
return ''.join(['&#%d;' % ord(c) for c in text])
def permissions(flags):
if "l" in flags:
return "lrwxrwxrwx"
if "x" in flags:
return "-rwxr-xr-x"
return "-rw-r--r--"
def person(author):
"Yann E. MORIN"
templates/filters: strip quotes from {author|person}...
r16235 """:person: Any text. Returns the name before an email address,
interpreting it as per RFC 5322.
"Yann E. MORIN"
templates/filters: add doctest to the 'person' filter...
r16251
>>> person('foo@bar')
'foo'
>>> person('Foo Bar <foo@bar>')
'Foo Bar'
>>> person('"Foo Bar" <foo@bar>')
'Foo Bar'
>>> person('"Foo \"buz\" Bar" <foo@bar>')
'Foo "buz" Bar'
>>> # The following are invalid, but do exist in real-life
...
>>> person('Foo "buz" Bar <foo@bar>')
'Foo "buz" Bar'
>>> person('"Foo Bar <foo@bar>')
'Foo Bar'
"Yann E. MORIN"
templates/filters: strip quotes from {author|person}...
r16235 """
Brodie Rao
cleanup: "not x in y" -> "x not in y"
r16686 if '@' not in author:
Patrick Mezard
templatefilters: sort function definitions
r13588 return author
f = author.find('<')
Adrian Buehlmann
templatefilters: improve person() for john.doe@example.com...
r13951 if f != -1:
"Yann E. MORIN"
templates/filters: strip quotes from {author|person}...
r16235 return author[:f].strip(' "').replace('\\"', '"')
Adrian Buehlmann
templatefilters: improve person() for john.doe@example.com...
r13951 f = author.find('@')
return author[:f].replace('.', ' ')
Patrick Mezard
templatefilters: sort function definitions
r13588
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 def rfc3339date(text):
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 """:rfc3339date: Date. Returns a date using the Internet date format
specified in RFC 3339: "2009-08-18T13:00:13+02:00".
"""
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 return util.datestr(text, "%Y-%m-%dT%H:%M:%S%1:%2")
def rfc822date(text):
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 """:rfc822date: Date. Returns a date using the same format used in email
headers: "Tue, 18 Aug 2009 13:00:13 +0200".
"""
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 return util.datestr(text, "%a, %d %b %Y %H:%M:%S %1%2")
def short(text):
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 """:short: Changeset hash. Returns the short form of a changeset hash,
i.e. a 12 hexadecimal digit string.
"""
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 return text[:12]
"Yann E. MORIN"
templates: add 'bisect' keyword to return a cset's bisect status...
r15155 def shortbisect(text):
""":shortbisect: Any text. Treats `text` as a bisection status, and
returns a single-character representing the status (G: good, B: bad,
S: skipped, U: untested, I: ignored). Returns single space if `text`
is not a valid bisection status.
"""
return hbisect.shortlabel(text) or ' '
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 def shortdate(text):
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 """:shortdate: Date. Returns a date like "2006-09-18"."""
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 return util.shortdate(text)
def stringescape(text):
return text.encode('string_escape')
Patrick Mezard
templatefilters: sort function definitions
r13588 def stringify(thing):
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 """:stringify: Any type. Turns the value into text by converting values into
text and concatenating them.
"""
Augie Fackler
globally: use safehasattr(x, '__iter__') instead of hasattr(x, '__iter__')
r14944 if util.safehasattr(thing, '__iter__') and not isinstance(thing, str):
Patrick Mezard
templatefilters: sort function definitions
r13588 return "".join([stringify(t) for t in thing if t is not None])
return str(thing)
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 def strip(text):
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 """:strip: Any text. Strips all leading and trailing whitespace."""
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 return text.strip()
Aleix Conchillo Flaque
templatefilters: add new stripdir filter...
r8158 def stripdir(text):
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 """:stripdir: Treat the text as path and strip a directory level, if
possible. For example, "foo" and "foo/bar" becomes "foo".
"""
Aleix Conchillo Flaque
templatefilters: add new stripdir filter...
r8158 dir = os.path.dirname(text)
if dir == "":
return os.path.basename(text)
else:
return dir
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 def tabindent(text):
Matt Mackall
template: fix tabindent docstring (issue2880)
r19467 """:tabindent: Any text. Returns the text, with every non-empty line
except the first starting with a tab character.
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 """
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 return indent(text, '\t')
def urlescape(text):
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 """:urlescape: Any text. Escapes all "special" characters. For example,
"foo bar" becomes "foo%20bar".
"""
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 return urllib.quote(text)
def userfilter(text):
Matteo Capobianco
templates/filters: extracting the user portion of an email address...
r16360 """:user: Any text. Returns a short representation of a user name or email
address."""
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 return util.shortuser(text)
Matteo Capobianco
templates/filters: extracting the user portion of an email address...
r16360 def emailuser(text):
""":emailuser: Any text. Returns the user portion of an email address."""
return util.emailuser(text)
Patrick Mezard
templatefilters: sort function definitions
r13588 def xmlescape(text):
text = (text
.replace('&', '&amp;')
.replace('<', '&lt;')
.replace('>', '&gt;')
.replace('"', '&quot;')
.replace("'", '&#39;')) # &apos; invalid in HTML
return re.sub('[\x00-\x08\x0B\x0C\x0E-\x1F]', ' ', text)
Rocco Rutte
templatefilters: add "nonempty" template filter...
r8234
Matt Mackall
templates: move filters to their own module...
r5976 filters = {
Patrick Mezard
templatefilters: match filter keys and function names
r13587 "addbreaks": addbreaks,
Patrick Mezard
templatefilters: sort filters table
r13586 "age": age,
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 "basename": basename,
"date": datefilter,
Matt Mackall
templates: move filters to their own module...
r5976 "domain": domain,
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 "email": email,
"escape": escape,
"fill68": fill68,
"fill76": fill76,
Matt Mackall
templates: move filters to their own module...
r5976 "firstline": firstline,
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 "hex": hexfilter,
"hgdate": hgdate,
"isodate": isodate,
"isodatesec": isodatesec,
Dirkjan Ochtman
templatefilters: split out jsonescape() function
r8014 "json": json,
"jsonescape": jsonescape,
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 "localdate": localdate,
Rocco Rutte
templatefilters: add "nonempty" template filter...
r8234 "nonempty": nonempty,
Matt Mackall
templates: move filters to their own module...
r5976 "obfuscate": obfuscate,
"permissions": permissions,
"person": person,
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 "rfc3339date": rfc3339date,
"rfc822date": rfc822date,
"short": short,
"Yann E. MORIN"
templates: add 'bisect' keyword to return a cset's bisect status...
r15155 "shortbisect": shortbisect,
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 "shortdate": shortdate,
"stringescape": stringescape,
Dirkjan Ochtman
templater: provide the standard template filters by default
r8360 "stringify": stringify,
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 "strip": strip,
Patrick Mezard
templatefilters: sort filters table
r13586 "stripdir": stripdir,
Patrick Mezard
templatefilters: wrap all filters in dedicated functions...
r13590 "tabindent": tabindent,
"urlescape": urlescape,
"user": userfilter,
Matteo Capobianco
templates/filters: extracting the user portion of an email address...
r16360 "emailuser": emailuser,
Jesse Glick
Permit XML entities to be escaped in template output....
r6174 "xmlescape": xmlescape,
Dirkjan Ochtman
add graph page to hgweb
r6691 }
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591
Angel Ezquerra
hgweb: add websub template filter...
r18627 def websub(text, websubtable):
""":websub: Any text. Only applies to hgweb. Applies the regular
expression replacements defined in the websub section.
"""
if websubtable:
for regexp, format in websubtable:
text = regexp.sub(format, text)
return text
Patrick Mezard
templatefilters: move doc from templates.txt to docstrings
r13591 # tell hggettext to extract docstrings from these functions:
i18nfunctions = filters.values()