# HG changeset patch # User mpm@selenic.com # Date 1117602610 28800 # Node ID f918a6fa2572c9f17d81b1fa027f17ba10f0a19f # Parent 8450c18f2a45796d97f0857ce7549a661923bf2f hgweb: add template filters, template style maps, and raw pages -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 hgweb: add template filters, template style maps, and raw pages Template filters: in templates, you can now specify a chain of filters like #desc|firstline|escape# #desc|escape|addbreaks# #date|age# to specify how you'd like raw text (or whatever) to be transformed. Template style maps: add ;style=foo to a URL and we'll use templates/map-foo if it exists. Raw output: Together, these two features make it east to implement raw downloadable files and patches. Simply link to the same page with style=raw and present the output as unfiltered text/plain with that template. manifest hash: 5954a648b3d6b4e6dc2dcd1975f96b4b0178da2a -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.0 (GNU/Linux) iD8DBQFCnUMyywK+sNU5EO8RAkKjAJ9h9JElSCbWBPUnL+koCSDxgo38AwCgrccM 0qwyKdh/fUNglICxSh3HBNA= =Svlo -----END PGP SIGNATURE----- diff -r 8450c18f2a45 -r f918a6fa2572 mercurial/hgweb.py --- a/mercurial/hgweb.py Tue May 31 09:03:46 2005 -0800 +++ b/mercurial/hgweb.py Tue May 31 21:10:10 2005 -0800 @@ -14,9 +14,9 @@ from mercurial.hg import * def templatepath(): - for f in "templates/map", "../templates/map": + for f in "templates", "../templates": p = os.path.join(os.path.dirname(__file__), f) - if os.path.isfile(p): return p + if os.path.isdir(p): return p def age(t): def plural(t, c): @@ -43,7 +43,7 @@ if n >= 2 or s == 1: return fmt(t, n) def nl2br(text): - return text.replace('\n', '
') + return text.replace('\n', '
\n') def obfuscate(text): return ''.join([ '&#%d' % ord(c) for c in text ]) @@ -67,23 +67,31 @@ else: sys.stdout.write(str(thing)) -def template(tmpl, **map): +def template(tmpl, filters = {}, **map): while tmpl: - m = re.search(r"#([a-zA-Z0-9]+)#", tmpl) + m = re.search(r"#([a-zA-Z0-9]+)((\|[a-zA-Z0-9]+)*)#", tmpl) if m: yield tmpl[:m.start(0)] v = map.get(m.group(1), "") - yield callable(v) and v() or v + v = callable(v) and v() or v + + fl = m.group(2) + if fl: + for f in fl.split("|")[1:]: + v = filters[f](v) + + yield v tmpl = tmpl[m.end(0):] else: yield tmpl return class templater: - def __init__(self, mapfile): + def __init__(self, mapfile, filters = {}): self.cache = {} self.map = {} self.base = os.path.dirname(mapfile) + self.filters = filters for l in file(mapfile): m = re.match(r'(\S+)\s*=\s*"(.*)"$', l) @@ -101,20 +109,27 @@ tmpl = self.cache[t] except KeyError: tmpl = self.cache[t] = file(self.map[t]).read() - return template(tmpl, **map) + return template(tmpl, self.filters, **map) class hgweb: maxchanges = 20 maxfiles = 10 - def __init__(self, path, name, templatemap = ""): - templatemap = templatemap or templatepath() - + def __init__(self, path, name, templates = ""): + self.templates = templates or templatepath() self.reponame = name self.repo = repository(ui(), path) - self.t = templater(templatemap) self.viewonly = 0 + self.filters = { + "escape": cgi.escape, + "age": age, + "date": (lambda x: time.asctime(time.gmtime(x))), + "addbreaks": nl2br, + "obfuscate": obfuscate, + "firstline": (lambda x: x.splitlines(1)[0]), + } + def date(self, cs): return time.asctime(time.gmtime(float(cs[2].split(' ')[0]))) @@ -154,15 +169,14 @@ def prettyprintlines(diff): for l in diff.splitlines(1): - line = cgi.escape(l) - if line.startswith('+'): - yield self.t("difflineplus", line = line) - elif line.startswith('-'): - yield self.t("difflineminus", line = line) - elif line.startswith('@'): - yield self.t("difflineat", line = line) + if l.startswith('+'): + yield self.t("difflineplus", line = l) + elif l.startswith('-'): + yield self.t("difflineminus", line = l) + elif l.startswith('@'): + yield self.t("difflineat", line = l) else: - yield self.t("diffline", line = line) + yield self.t("diffline", line = l) r = self.repo cl = r.changelog @@ -234,9 +248,7 @@ l.insert(0, self.t( 'changelogentry', parity = parity, - author = obfuscate(changes[1]), - shortdesc = cgi.escape(changes[4].splitlines()[0]), - age = age(t), + author = changes[1], parent1 = self.parent("changelogparent", hex(p1), cl.rev(p1)), parent2 = self.parent("changelogparent", @@ -244,8 +256,8 @@ p1 = hex(p1), p2 = hex(p2), p1rev = cl.rev(p1), p2rev = cl.rev(p2), manifest = hex(changes[0]), - desc = nl2br(cgi.escape(changes[4])), - date = time.asctime(time.gmtime(t)), + desc = changes[4], + date = t, files = self.listfilediffs(changes[3], n), rev = i, node = hn)) @@ -292,7 +304,6 @@ diff = diff, rev = cl.rev(n), node = nodeid, - shortdesc = cgi.escape(changes[4].splitlines()[0]), parent1 = self.parent("changesetparent", hex(p1), cl.rev(p1)), parent2 = self.parent("changesetparent", @@ -300,9 +311,9 @@ p1 = hex(p1), p2 = hex(p2), p1rev = cl.rev(p1), p2rev = cl.rev(p2), manifest = hex(changes[0]), - author = obfuscate(changes[1]), - desc = nl2br(cgi.escape(changes[4])), - date = time.asctime(time.gmtime(t)), + author = changes[1], + desc = changes[4], + date = t, files = files) def filelog(self, f, filenode): @@ -329,10 +340,9 @@ filerev = i, file = f, node = hex(cn), - author = obfuscate(cs[1]), - age = age(t), - date = time.asctime(time.gmtime(t)), - shortdesc = cgi.escape(cs[4].splitlines()[0]), + author = cs[1], + date = t, + desc = cs[4], p1 = hex(p1), p2 = hex(p2), p1rev = fl.rev(p1), p2rev = fl.rev(p2))) parity = 1 - parity @@ -350,7 +360,7 @@ def filerevision(self, f, node): fl = self.repo.file(f) n = bin(node) - text = cgi.escape(fl.read(n)) + text = fl.read(n) changerev = fl.linkrev(n) cl = self.repo.changelog cn = cl.node(changerev) @@ -361,8 +371,7 @@ def lines(): for l, t in enumerate(text.splitlines(1)): - yield self.t("fileline", - line = t, + yield self.t("fileline", line = t, linenumber = "% 6d" % (l + 1), parity = l & 1) @@ -376,10 +385,8 @@ rev = changerev, node = hex(cn), manifest = hex(mfn), - author = obfuscate(cs[1]), - age = age(t), - date = time.asctime(time.gmtime(t)), - shortdesc = cgi.escape(cs[4].splitlines()[0]), + author = cs[1], + date = t, parent1 = self.parent("filerevparent", hex(p1), fl.rev(p1), file=f), parent2 = self.parent("filerevparent", @@ -387,7 +394,6 @@ p1 = hex(p1), p2 = hex(p2), p1rev = fl.rev(p1), p2rev = fl.rev(p2)) - def fileannotate(self, f, node): bcache = {} ncache = {} @@ -431,7 +437,7 @@ rev = r, author = name, file = f, - line = cgi.escape(l)) + line = l) yield self.t("fileannotate", header = self.header(), @@ -444,10 +450,8 @@ rev = changerev, node = hex(cn), manifest = hex(mfn), - author = obfuscate(cs[1]), - age = age(t), - date = time.asctime(time.gmtime(t)), - shortdesc = cgi.escape(cs[4].splitlines()[0]), + author = cs[1], + date = t, parent1 = self.parent("fileannotateparent", hex(p1), fl.rev(p1), file=f), parent2 = self.parent("fileannotateparent", @@ -563,6 +567,14 @@ def run(self): args = cgi.parse() + m = os.path.join(self.templates, "map") + if args.has_key('style'): + b = os.path.basename("map-" + args['style'][0]) + p = os.path.join(self.templates, b) + if os.path.isfile(p): m = p + + self.t = templater(m, self.filters) + if not args.has_key('cmd') or args['cmd'][0] == 'changelog': hi = self.repo.changelog.count() if args.has_key('rev'): diff -r 8450c18f2a45 -r f918a6fa2572 templates/changelog.tmpl --- a/templates/changelog.tmpl Tue May 31 09:03:46 2005 -0800 +++ b/templates/changelog.tmpl Tue May 31 21:10:10 2005 -0800 @@ -1,5 +1,5 @@ #header# -#repo#: changelog +#repo|escape#: changelog @@ -8,7 +8,7 @@ manifest -

changelog for #repo#

+

changelog for #repo|escape#

search: diff -r 8450c18f2a45 -r f918a6fa2572 templates/changelogentry.tmpl --- a/templates/changelogentry.tmpl Tue May 31 09:03:46 2005 -0800 +++ b/templates/changelogentry.tmpl Tue May 31 21:10:10 2005 -0800 @@ -1,8 +1,8 @@
- - + @@ -13,7 +13,7 @@ - + diff -r 8450c18f2a45 -r f918a6fa2572 templates/changeset-raw.tmpl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/templates/changeset-raw.tmpl Tue May 31 21:10:10 2005 -0800 @@ -0,0 +1,10 @@ +#header# +# HG changeset patch +# User #author# +# Date #date|date# +# Node ID #node# +#parent1# +#parent2# +#desc# + +#diff# diff -r 8450c18f2a45 -r f918a6fa2572 templates/changeset.tmpl --- a/templates/changeset.tmpl Tue May 31 09:03:46 2005 -0800 +++ b/templates/changeset.tmpl Tue May 31 21:10:10 2005 -0800 @@ -1,5 +1,5 @@ #header# -#repo#: changeset #node# +#repo|escape#: changeset #node# @@ -7,9 +7,10 @@ changelogtagsmanifest +raw -

changeset: #shortdesc#

+

changeset: #desc|escape|firstline#

#age# ago: #shortdesc# + #date|age# ago: #desc|firstline|escape#
changeset #rev#:  #node#
#author#
date: #date#
#date|date#
files #files#
@@ -22,16 +23,16 @@ - + - + - +
#manifest#
author:#author#
#author|obfuscate#
date:#date#
#date|date# (#date|age# ago)
files: #files#
description:#desc#
#desc|escape|addbreaks#
diff -r 8450c18f2a45 -r f918a6fa2572 templates/fileannotate.tmpl
--- a/templates/fileannotate.tmpl	Tue May 31 09:03:46 2005 -0800
+++ b/templates/fileannotate.tmpl	Tue May 31 21:10:10 2005 -0800
@@ -1,5 +1,5 @@
 #header#
-#repo#: #file# annotate
+#repo|escape#: #file# annotate
 
 
 
@@ -25,10 +25,10 @@
  #manifest#
 
  author:
- #author#
+ #author|obfuscate#
 
  date:
- #date#
+ #date|date# (#date|age#) ago)
 
 
 
diff -r 8450c18f2a45 -r f918a6fa2572 templates/filediff-raw.tmpl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/templates/filediff-raw.tmpl Tue May 31 21:10:10 2005 -0800 @@ -0,0 +1,5 @@ +#header# +#diff# +#footer# + + diff -r 8450c18f2a45 -r f918a6fa2572 templates/filediff.tmpl --- a/templates/filediff.tmpl Tue May 31 09:03:46 2005 -0800 +++ b/templates/filediff.tmpl Tue May 31 21:10:10 2005 -0800 @@ -1,5 +1,5 @@ #header# -#repo#: #file# diff +#repo|escape#: #file# diff @@ -10,6 +10,7 @@ file revisions annotate +raw

#file#

diff -r 8450c18f2a45 -r f918a6fa2572 templates/filelog.tmpl --- a/templates/filelog.tmpl Tue May 31 09:03:46 2005 -0800 +++ b/templates/filelog.tmpl Tue May 31 21:10:10 2005 -0800 @@ -1,5 +1,5 @@ #header# -#repo#: #file# history +#repo|escape#: #file# history diff -r 8450c18f2a45 -r f918a6fa2572 templates/filelogentry.tmpl --- a/templates/filelogentry.tmpl Tue May 31 09:03:46 2005 -0800 +++ b/templates/filelogentry.tmpl Tue May 31 21:10:10 2005 -0800 @@ -1,7 +1,7 @@ - - + - + - +
#age# ago: #shortdesc# + #date|age# ago: #desc|firstline|escape#
revision #filerev#:  #filenode# @@ -10,10 +10,10 @@
author: #author#
#author|obfuscate#
date: #date#
#date|date# (#date|age# ago)
diff -r 8450c18f2a45 -r f918a6fa2572 templates/filerevision-raw.tmpl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/templates/filerevision-raw.tmpl Tue May 31 21:10:10 2005 -0800 @@ -0,0 +1,3 @@ +#header# +#text# +#footer# diff -r 8450c18f2a45 -r f918a6fa2572 templates/filerevision.tmpl --- a/templates/filerevision.tmpl Tue May 31 09:03:46 2005 -0800 +++ b/templates/filerevision.tmpl Tue May 31 21:10:10 2005 -0800 @@ -1,5 +1,5 @@ #header# -#repo#:#file# +#repo|escape#:#file# @@ -10,6 +10,7 @@ manifest revisions annotate +raw

#file# (revision #filenode#)

@@ -25,10 +26,10 @@ #manifest# author: - #author# + #author|obfuscate# date: - #date# + #date|date# (#date|age# ago)
diff -r 8450c18f2a45 -r f918a6fa2572 templates/header-raw.tmpl
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/header-raw.tmpl	Tue May 31 21:10:10 2005 -0800
@@ -0,0 +1,1 @@
+Content-type: text/plain
diff -r 8450c18f2a45 -r f918a6fa2572 templates/manifest.tmpl
--- a/templates/manifest.tmpl	Tue May 31 09:03:46 2005 -0800
+++ b/templates/manifest.tmpl	Tue May 31 21:10:10 2005 -0800
@@ -1,5 +1,5 @@
 #header#
-#repo#: manifest #manifest#
+#repo|escape#: manifest #manifest#
 
 
 
diff -r 8450c18f2a45 -r f918a6fa2572 templates/map
--- a/templates/map	Tue May 31 09:03:46 2005 -0800
+++ b/templates/map	Tue May 31 21:10:10 2005 -0800
@@ -14,13 +14,13 @@
 fileannotate = fileannotate.tmpl
 filediff = filediff.tmpl
 filelog = filelog.tmpl
-fileline = "
#linenumber# #line#
" +fileline = "
#linenumber# #line|escape#
" filelogentry = filelogentry.tmpl -annotateline = "#author#@#rev#
#line#
" -difflineplus = "#line#" -difflineminus = "#line#" -difflineat = "#line#" -diffline = "#line#" +annotateline = "#author#@#rev#
#line|escape#
" +difflineplus = "#line|escape#" +difflineminus = "#line|escape#" +difflineat = "#line|escape#" +diffline = "#line|escape#" changelogparent = "parent: #node#" changesetparent = "parent:#node#" filerevparent = "parent:#node#" diff -r 8450c18f2a45 -r f918a6fa2572 templates/map-raw --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/templates/map-raw Tue May 31 21:10:10 2005 -0800 @@ -0,0 +1,14 @@ +header = header-raw.tmpl +footer = "" +changeset = changeset-raw.tmpl +annotateline = "#author#@#rev#
#line#
" +difflineplus = "#line#" +difflineminus = "#line#" +difflineat = "#line#" +diffline = "#line#" +changesetparent = "# parent: #node#" +filenodelink = "#file#" +filerevision = filerevision-raw.tmpl +fileline = "#line#" +diffblock = "#lines#" +filediff = filediff-raw.tmpl