changeset 142:529bf610092e

Prettify the web interface Add header, footer templates Add null parent handling Combine files and directories Add parity flag for alternating line colors Add line numbers to filerevision
author mpm@selenic.com
date Mon, 23 May 2005 20:57:48 -0800
parents 5f471a75d607
children bf325dce498e
files hg mercurial/hgweb.py templates/changelog.tmpl templates/changelogentry.tmpl templates/changeset.tmpl templates/fileannotate.tmpl templates/filediff.tmpl templates/filelog.tmpl templates/filelogentry.tmpl templates/filerevision.tmpl templates/footer.tmpl templates/header.tmpl templates/manifest.tmpl templates/map
diffstat 14 files changed, 223 insertions(+), 137 deletions(-) [+]
line wrap: on
line diff
--- a/hg
+++ b/hg
@@ -463,7 +463,7 @@ elif cmd == "verify":
         except Exception, inst:
             ui.warn("unpacking manifest %s: %s\n" % (hg.short(n), inst))
             errors += 1
-            
+
         ff = [ l.split('\0') for l in delta.splitlines() ]
         for f, fn in ff:
             filenodes.setdefault(f, {})[hg.bin(fn)] = 1
--- a/mercurial/hgweb.py
+++ b/mercurial/hgweb.py
@@ -122,6 +122,10 @@ class hgweb:
         if len(files) > self.maxfiles:
             yield self.t("fileellipses")
 
+    def parent(self, t1, node, rev):
+        if node != hex(nullid):
+            yield self.t(t1, node = node, rev = rev)
+
     def diff(self, node1, node2, files):
         def filterfiles(list, files):
             l = [ x for x in list if x in files ]
@@ -169,6 +173,12 @@ class hgweb:
             tn = ""
             yield prettyprint(mdiff.unidiff(to, date1, tn, date2, f))
 
+    def header(self):
+        yield self.t("header", repo = self.reponame)
+
+    def footer(self):
+        yield self.t("footer", repo = self.reponame)
+
     def changelog(self, pos=None):
         def changenav():
             def seq(factor = 1):
@@ -191,6 +201,7 @@ class hgweb:
             yield self.t("naventry", rev = count - 1)
 
         def changelist():
+            parity = (start - end) & 1
             cl = self.repo.changelog
             l = [] # build a list in forward order for efficiency
             for i in range(start, end + 1):
@@ -202,9 +213,14 @@ class hgweb:
 
                 l.insert(0, self.t(
                     'changelogentry',
+                    parity = parity,
                     author = obfuscate(changes[1]),
                     shortdesc = cgi.escape(changes[4].splitlines()[0]),
                     age = age(t),
+                    parent1 = self.parent("changelogparent",
+                                          hex(p1), cl.rev(p1)),
+                    parent2 = self.parent("changelogparent",
+                                          hex(p2), cl.rev(p2)),
                     p1 = hex(p1), p2 = hex(p2),
                     p1rev = cl.rev(p1), p2rev = cl.rev(p2),
                     manifest = hex(changes[0]),
@@ -213,6 +229,7 @@ class hgweb:
                     files = self.listfilediffs(changes[3], n),
                     rev = i,
                     node = hn))
+                parity = 1 - parity
 
             yield l
 
@@ -222,8 +239,12 @@ class hgweb:
         start = max(0, pos - self.maxchanges)
         end = min(count - 1, start + self.maxchanges)
 
-        yield self.t('changelog', repo = self.reponame, changenav = changenav,
-                     rev = pos, changesets = count, changelist = changelist)
+        yield self.t('changelog',
+                     header = self.header(),
+                     footer = self.footer(),
+                     repo = self.reponame,
+                     changenav = changenav,
+                     rev = pos, changesets = count, entries = changelist)
 
     def changeset(self, nodeid):
         n = bin(nodeid)
@@ -243,10 +264,17 @@ class hgweb:
             yield self.diff(p1, n, changes[3])
 
         yield self.t('changeset',
+                     header = self.header(),
+                     footer = self.footer(),
+                     repo = self.reponame,
                      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",
+                                           hex(p2), cl.rev(p2)),
                      p1 = hex(p1), p2 = hex(p2),
                      p1rev = cl.rev(p1), p2rev = cl.rev(p2),
                      manifest = hex(changes[0]),
@@ -262,6 +290,8 @@ class hgweb:
 
         def entries():
             l = []
+            parity = (count - 1) & 1
+            
             for i in range(count):
 
                 n = fl.node(i)
@@ -272,6 +302,7 @@ class hgweb:
                 t = float(cs[2].split(' ')[0])
 
                 l.insert(0, self.t("filelogentry",
+                                   parity = parity,
                                    filenode = hex(n),
                                    filerev = i,
                                    file = f,
@@ -282,10 +313,14 @@ class hgweb:
                                    shortdesc = cgi.escape(cs[4].splitlines()[0]),
                                    p1 = hex(p1), p2 = hex(p2),
                                    p1rev = fl.rev(p1), p2rev = fl.rev(p2)))
+                parity = 1 - parity
 
             yield l
 
         yield self.t("filelog",
+                     header = self.header(),
+                     footer = self.footer(),
+                     repo = self.reponame,
                      file = f,
                      filenode = filenode,
                      entries = entries)
@@ -301,11 +336,21 @@ class hgweb:
         p1, p2 = fl.parents(n)
         t = float(cs[2].split(' ')[0])
         mfn = cs[0]
+
+        def lines():
+            for l, t in enumerate(text.splitlines(1)):
+                yield self.t("fileline",
+                             line = t,
+                             linenumber = "% 6d" % (l + 1),
+                             parity = l & 1)
         
         yield self.t("filerevision", file = f,
+                     header = self.header(),
+                     footer = self.footer(),
+                     repo = self.reponame,
                      filenode = node,
                      path = up(f),
-                     text = text,
+                     text = lines(),
                      rev = changerev,
                      node = hex(cn),
                      manifest = hex(mfn),
@@ -313,6 +358,10 @@ class hgweb:
                      age = age(t),
                      date = time.asctime(time.gmtime(t)),
                      shortdesc = cgi.escape(cs[4].splitlines()[0]),
+                     parent1 = self.parent("filerevparent",
+                                           hex(p1), fl.rev(p1)),
+                     parent2 = self.parent("filerevparent",
+                                           hex(p2), fl.rev(p2)),
                      p1 = hex(p1), p2 = hex(p2),
                      p1rev = fl.rev(p1), p2rev = fl.rev(p2))
 
@@ -332,6 +381,8 @@ class hgweb:
         mfn = cs[0]
 
         def annotate():
+            parity = 1
+            last = None
             for r, l in fl.annotate(n):
                 try:
                     cnode = ncache[r]
@@ -348,7 +399,12 @@ class hgweb:
                         name = name[:f]
                     bcache[r] = name
 
+                if last != cnode:
+                    parity = 1 - parity
+                    last = cnode
+
                 yield self.t("annotateline",
+                             parity = parity,
                              node = hex(cnode),
                              rev = r,
                              author = name,
@@ -356,6 +412,9 @@ class hgweb:
                              line = cgi.escape(l))
 
         yield self.t("fileannotate",
+                     header = self.header(),
+                     footer = self.footer(),
+                     repo = self.reponame,
                      file = f,
                      filenode = node,
                      annotate = annotate,
@@ -367,6 +426,10 @@ class hgweb:
                      age = age(t),
                      date = time.asctime(time.gmtime(t)),
                      shortdesc = cgi.escape(cs[4].splitlines()[0]),
+                     parent1 = self.parent("filerevparent",
+                                           hex(p1), fl.rev(p1)),
+                     parent2 = self.parent("filerevparent",
+                                           hex(p2), fl.rev(p2)),
                      p1 = hex(p1), p2 = hex(p2),
                      p1rev = fl.rev(p1), p2rev = fl.rev(p2))
 
@@ -375,10 +438,8 @@ class hgweb:
         rev = self.repo.manifest.rev(bin(mnode))
         node = self.repo.changelog.node(rev)
 
-        dirs = {}
         files = {}
-        short = {}
-
+ 
         p = path[1:]
         l = len(p)
 
@@ -388,37 +449,41 @@ class hgweb:
             remain = f[l:]
             if "/" in remain:
                 short = remain[:remain.find("/") + 1] # bleah
-                dirs[short] = 1
+                files[short] = (f, None)
             else:
                 short = os.path.basename(remain)
                 files[short] = (f, n)
 
-        def dirlist():
-            dl = dirs.keys()
-            dl.sort()
-            
-            for d in dl:
-                yield self.t("manifestdirentry",
-                             path = os.path.join(path, d),
-                             manifest = mnode, basename = d[:-1])
-
         def filelist():
+            parity = 0
             fl = files.keys()
             fl.sort()
             for f in fl:
                 full, fnode = files[f]
-                yield self.t("manifestfileentry",
-                             file = full, manifest = mnode, filenode = hex(fnode),
-                             basename = f)
+                if fnode:
+                    yield self.t("manifestfileentry",
+                                 file = full,
+                                 manifest = mnode,
+                                 filenode = hex(fnode),
+                                 parity = parity,
+                                 basename = f)
+                else:
+                    yield self.t("manifestdirentry",
+                                 parity = parity,
+                                 path = os.path.join(path, f),
+                                 manifest = mnode, basename = f[:-1])
+                parity = 1 - parity
 
         yield self.t("manifest",
+                     header = self.header(),
+                     footer = self.footer(),
+                     repo = self.reponame,
                      manifest = mnode,
                      rev = rev,
                      node = hex(node),
                      path = path,
                      up = up(path),
-                     dirs = dirlist,
-                     files = filelist)
+                     entries = filelist)
 
     def filediff(self, file, changeset):
         n = bin(changeset)
@@ -431,6 +496,9 @@ class hgweb:
             yield self.diff(p1, n, file)
 
         yield self.t("filediff",
+                     header = self.header(),
+                     footer = self.footer(),
+                     repo = self.reponame,
                      file = file,
                      filenode = hex(mf[file]),
                      node = changeset,
@@ -439,12 +507,7 @@ class hgweb:
                      p1rev = self.repo.changelog.rev(p1),
                      diff = diff)
                      
-    # header and footer, css
     # add tags to things
-    # show parents
-    # diff between rev and parent in changeset and file
-    # manifest links
-    # browse at top
     # tags -> list of changesets corresponding to tags
     # find tag, changeset, file
 
--- a/templates/changelog.tmpl
+++ b/templates/changelog.tmpl
@@ -1,16 +1,13 @@
-Content-Type: text/html
-
-<html>
+#header#
+<title>#repo#: changelog</title>
+</head>
 <body>
 <h2>changelog for #repo#</h2>
 
 navigate: #changenav#<br>
 
-<table>
-#changelist#
-</table>
+#entries#
 
 navigate: #changenav#<br>
 
-</body>
-</html>
\ No newline at end of file
+#footer#
--- a/templates/changelogentry.tmpl
+++ b/templates/changelogentry.tmpl
@@ -1,26 +1,25 @@
+<div class=parity#parity#>
+<table width=100% cellpadding=0 cellspacing=0>
 <tr>
- <td align=right width="15%"><b>#age# ago:</b></td>
+ <td align=right width="15%"><b>#age# ago:&nbsp;</b></td>
  <td><b>#shortdesc#</b></td</tr>
 <tr>
- <td align=right>revision:</td>
+ <td align=right>revision:&nbsp;</td>
  <td><a href="?cmd=changeset;node=#node#">#rev#:#node#</a></td></tr>
+#parent1#
+#parent2#
 <tr>
- <td align=right>parent:</td>
- <td><a href="?cmd=changeset;node=#p1#">#p1rev#:#p1#</a></td></tr>
-<tr>
- <td align=right>parent:</td>
- <td><a href="?cmd=changeset;node=#p2#">#p2rev#:#p2#</a></td></tr>
-<tr>
- <td align=right>manifest:</td>
+ <td align=right>manifest:&nbsp;</td>
  <td><a href="?cmd=manifest;manifest=#manifest#;path=/">#rev#:#manifest#</a></td></tr>
 <tr>
- <td align=right>author:</td>
+ <td align=right>author:&nbsp;</td>
  <td>#author#</td></tr>
 <tr>
- <td align=right>date:</td>
+ <td align=right>date:&nbsp;</td>
  <td>#date#</td></tr>
 <tr>
- <td align=right valign=top>files:</td>
+ <td align=right valign=top>files:&nbsp;</td>
  <td>#files#</td></tr>
+</table>
+</div>
 
-
--- a/templates/changeset.tmpl
+++ b/templates/changeset.tmpl
@@ -1,42 +1,39 @@
-Content-type: text/html
+#header#
+<title>#repo#: changeset #node#</title>
+</head>
+<body>
 
-<html>
-<body>
+<div class=buttons>
 <a href="?cmd=changelog&pos=#rev#">changelog</a>
 <a href="?cmd=manifest;manifest=#manifest#;path=/">manifest</a>
+</div>
 
 <h2>changeset: #shortdesc#</h2>
 
 <table>
 <tr>
- <td align=right>revision:</td>
+ <td class=metatag>revision:</td>
  <td><a href="?cmd=changeset;node=#node#">#rev#:#node#</a></td></tr>
+#parent1#
+#parent2#
 <tr>
- <td align=right>parent:</td>
- <td><a href="?cmd=changeset;node=#p1#">#p1rev#:#p1#</a></td></tr>
-<tr>
- <td align=right>parent:</td>
- <td><a href="?cmd=changeset;node=#p2#">#p2rev#:#p2#</a></td></tr>
-<tr>
- <td align=right>manifest:</td>
+ <td class=metatag>manifest:</td>
  <td><a href="?cmd=manifest;manifest=#manifest#;path=/">#rev#:#manifest#</a></td></tr>
 <tr>
- <td align=right>author:</td>
+ <td class=metatag>author:</td>
  <td>#author#</td></tr>
 <tr>
- <td align=right>date:</td>
+ <td class=metatag>date:</td>
  <td>#date#</td></tr>
 <tr>
- <td align=right valign=top>files:</td>
+ <td class=metatag valign=top>files:</td>
  <td>#files#</td></tr>
 <tr>
- <td align=right valign=top>description:</td>
+ <td class=metatag valign=top>description:</td>
  <td>#desc#</td></tr>
 </table>
 
-<hr />
-
-<pre>
+<pre class=parity0>
 #diff#
 </pre>
 
--- a/templates/fileannotate.tmpl
+++ b/templates/fileannotate.tmpl
@@ -1,42 +1,39 @@
-Content-type: text/html
-
-<html>
+#header#
+<title>#repo#: #file# annotate</title>
+</head>
 <body>
 
+<div class=buttons>
 <a href="?cmd=changelog&rev=#rev#">changelog</a>
 <a href="?cmd=changeset&node=#node#">changeset</a>
 <a href="?cmd=manifest&manifest=#manifest#;path=#path#">manifest</a>
 <a href="?cmd=file&file=#file#&filenode=#filenode#">file</a>
 <a href="?cmd=filelog&file=#file#;filenode=#filenode#">revisions</a>
+</div>
 
 <h2>Annotate #file# (#filenode#)</h2>
 
 <table>
 <tr>
- <td align=right>changeset:</td>
+ <td class=metatag>changeset:</td>
  <td><a href="?cmd=changeset;node=#node#">#rev#:#node#</a></td></tr>
+#parent1#
+#parent2#
 <tr>
- <td align=right>parent:</td>
- <td><a href="?cmd=file;file=#file#;node=#p1#">#p1rev#:#p1#</a></td></tr>
-<tr>
- <td align=right>parent:</td>
- <td><a href="?cmd=file;file=#file#;node=#p2#">#p2rev#:#p2#</a></td></tr>
-<tr>
- <td align=right>manifest:</td>
+ <td class=metatag>manifest:</td>
  <td><a href="?cmd=manifest;manifest=#manifest#;path=/">#rev#:#manifest#</a></td></tr>
 <tr>
- <td align=right>author:</td>
+ <td class=metatag>author:</td>
  <td>#author#</td></tr>
 <tr>
- <td align=right>date:</td>
+ <td class=metatag>date:</td>
  <td>#date#</td></tr>
 </table>
 
-<hr />
+<br/>
 
-<table>
+<table cellspacing=0 cellpadding=0>
 #annotate#
 </table>
 
-</body>
-</html>
\ No newline at end of file
+#footer#
--- a/templates/filediff.tmpl
+++ b/templates/filediff.tmpl
@@ -1,30 +1,31 @@
-Content-type: text/html
+#header#
+<title>#repo#: #file# diff</title>
+</head>
+<body>
 
-<html>
-<body>
+<div class=buttons>
 <a href="?cmd=changelog&rev=#rev#">changelog</a>
 <a href="?cmd=changeset&node=#node#">changeset</a>
 <a href="?cmd=file&file=#file#&filenode=#filenode#">file</a>
 <a href="?cmd=filelog&file=#file#&filenode=#filenode#">revisions</a>
 <a href="?cmd=annotate&file=#file#&filenode=#filenode#">annotate</a>
+</div>
 
 <h2>#file#</h2>
 
 <table>
 <tr>
- <td align=right>revision:</td>
+ <td class=metatag>revision:</td>
  <td><a href="?cmd=changeset;node=#node#">#rev#:#node#</a></td></tr>
 <tr>
- <td align=right>parent:</td>
+ <td class=metatag>parent:</td>
  <td><a href="?cmd=changeset;node=#p1#">#p1rev#:#p1#</a></td></tr>
 </table>
 
-<hr />
-<pre>
+<pre class=parity0>
 #diff#
 </pre>
 
-</body>
-</html
+#footer#
 
 
--- a/templates/filelog.tmpl
+++ b/templates/filelog.tmpl
@@ -1,17 +1,16 @@
-Content-type: text/html
-
-<html>
+#header#
+<title>#repo#: #file# history</title>
+</head>
 <body>
 
+<div class=buttons>
 <a href="?cmd=changelog">changelog</a>
 <a href="?cmd=file&file=#file#&filenode=#filenode#">file</a>
 <a href="?cmd=annotate&file=#file#&filenode=#filenode#">annotate</a>
+</div>
 
 <h2>#file# revision history</h2>
 
-<table>
 #entries#
-</table>
 
-</body>
-</html>
\ No newline at end of file
+#footer#
--- a/templates/filelogentry.tmpl
+++ b/templates/filelogentry.tmpl
@@ -1,18 +1,19 @@
+<table class=parity#parity# width=100% cellspacing=0 cellpadding=0>
 <tr>
- <td align=right width="15%"><b>#age# ago:</b></td>
- <td><b><a href="?cmd=changeset;node=#changeset#">#shortdesc#</a></b></td</tr>
+ <td align=right width="15%"><b>#age# ago:&nbsp;</b></td>
+ <td><b><a href="?cmd=changeset;node=#node#">#shortdesc#</a></b></td</tr>
 <tr>
- <td align=right>revision:</td>
+ <td align=right>revision:&nbsp;</td>
  <td><a href="?cmd=file;file=#file#;filenode=#filenode#">#filerev#:#filenode#</a>
 <a href="?cmd=filediff;file=#file#;node=#node#">(diff)</a>
 <a href="?cmd=annotate;file=#file#;filenode=#filenode#">(annotate)</a>
 </td></tr>
 <tr>
- <td align=right>author:</td>
+ <td align=right>author:&nbsp;</td>
  <td>#author#</td></tr>
 <tr>
- <td align=right>date:</td>
+ <td align=right>date:&nbsp;</td>
  <td>#date#</td></tr>
+</table>
 
 
-
--- a/templates/filerevision.tmpl
+++ b/templates/filerevision.tmpl
@@ -1,42 +1,37 @@
-Content-type: text/html
-
-<html>
+#header#
+<title>#repo#:#file#</title>
+</head>
 <body>
 
+<div class=buttons>
 <a href="?cmd=changelog&rev=#rev#">changelog</a>
 <a href="?cmd=changeset&node=#node#">changeset</a>
 <a href="?cmd=manifest&manifest=#manifest#;path=#path#">manifest</a>
 <a href="?cmd=filelog&file=#file#;filenode=#filenode#">revisions</a>
 <a href="?cmd=annotate&file=#file#&filenode=#filenode#">annotate</a>
+</div>
 
 <h2>#file# (revision #filenode#)</h2>
 
 <table>
 <tr>
- <td align=right>changeset:</td>
+ <td class=metatag>changeset:</td>
  <td><a href="?cmd=changeset;node=#node#">#rev#:#node#</a></td></tr>
+#parent1#
+#parent2#
 <tr>
- <td align=right>parent:</td>
- <td><a href="?cmd=file;file=#file#;node=#p1#">#p1rev#:#p1#</a></td></tr>
-<tr>
- <td align=right>parent:</td>
- <td><a href="?cmd=file;file=#file#;node=#p2#">#p2rev#:#p2#</a></td></tr>
-<tr>
- <td align=right>manifest:</td>
+ <td class=metatag>manifest:</td>
  <td><a href="?cmd=manifest;manifest=#manifest#;path=/">#rev#:#manifest#</a></td></tr>
 <tr>
- <td align=right>author:</td>
+ <td class=metatag>author:</td>
  <td>#author#</td></tr>
 <tr>
- <td align=right>date:</td>
+ <td class=metatag>date:</td>
  <td>#date#</td></tr>
 </table>
 
-<hr />
-
 <pre>
 #text#
 </pre>
 
-</body>
-</html>
\ No newline at end of file
+#footer#
new file mode 100644
--- /dev/null
+++ b/templates/footer.tmpl
@@ -0,0 +1,2 @@
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/templates/header.tmpl
@@ -0,0 +1,31 @@
+Content-type: text/html
+
+<html>
+<head>
+</head>
+<style type="text/css">
+a { text-decoration:none; }
+.parity0 { background-color: #eeeeee; }
+.parity1 { background-color: #ffffff; }
+.lineno { width: 60px; color: #cccccc; font-size: smaller; }
+.plusline { color: green; }
+.minusline { color: red; }
+.atline { color: purple; }
+.annotate { font-size: smaller; text-align: right; padding-right: 1em; }
+.buttons a {
+  background-color: #666666;
+  padding: 2pt;
+  color: white;
+  font-family: sans;
+  font-weight: bold;
+}
+.metatag {
+  background-color: #888888;
+  color: white;
+  text-align: right; 
+}
+
+</style>
+</head>
+<body>
+
--- a/templates/manifest.tmpl
+++ b/templates/manifest.tmpl
@@ -1,19 +1,16 @@
-Content-Type: text/html
-
-<html>
+#header#
+<title>#repo#: manifest #manifest#</title>
+</head>
 <body>
 
+<div class=buttons>
 <a href="?cmd=changelog&rev=#rev#">changelog</a>
 <a href="?cmd=changeset&node=#node#">changeset</a>
+</div>
 
 <h2>manifest: #path#</h2>
-<p>(#rev#:#manifest#)</p>
 
-<p>
-<a href="?cmd=manifest;manifest=#manifest#;path=#up#">[up]</a><br />
-#dirs#</p>
+<div class=parity1><a href="?cmd=manifest;manifest=#manifest#;path=#up#">[up]</a><br /></div>
+#entries#
 
-<p>#files#</p>
-
-</body>
-</html>
\ No newline at end of file
+#footer#
\ No newline at end of file
--- a/templates/map
+++ b/templates/map
@@ -1,3 +1,5 @@
+header = header.tmpl
+footer = footer.tmpl
 changelog = changelog.tmpl
 naventry = "<a href="?cmd=changelog;pos=#rev#">#rev#</a> "
 filedifflink = "<a href="?cmd=filediff;node=#node#;file=#file#">#file#</a> "
@@ -6,15 +8,20 @@ fileellipses = "..."
 changelogentry = changelogentry.tmpl
 changeset = changeset.tmpl
 manifest = manifest.tmpl
-manifestdirentry = "<a href="?cmd=manifest;manifest=#manifest#;path=#path#">#basename#/</a><br />"
-manifestfileentry = "<a href="?cmd=file;filenode=#filenode#;file=#file#">#basename#</a><br /> "
+manifestdirentry = "<div class=parity#parity#><a href="?cmd=manifest;manifest=#manifest#;path=#path#">#basename#/</a><br /></div>"
+manifestfileentry = "<div class=parity#parity#><a href="?cmd=file;filenode=#filenode#;file=#file#">#basename#</a><br /></div>"
 filerevision = filerevision.tmpl
 fileannotate = fileannotate.tmpl
 filediff = filediff.tmpl
 filelog = filelog.tmpl
+fileline = "<div class=parity#parity#><span class=lineno>#linenumber# </span>#line#</div>"
 filelogentry = filelogentry.tmpl
-annotateline = "<tr><td align = right><a href="?cmd=changeset;node=#node#">#author#@#rev#</a>:</td><td><pre>#line#</pre></td></tr>"
+annotateline = "<tr class=parity#parity#><td class=annotate><a href="?cmd=changeset;node=#node#">#author#@#rev#</a></td><td><pre>#line#</pre></td></tr>"
 difflineplus = "<span class=plusline>#line#</span>"
 difflineminus = "<span class=minusline>#line#</span>"
 difflineat = "<span class=atline>#line#</span>"
-diffline = "#line#"
\ No newline at end of file
+diffline = "#line#"
+changelogparent = "<tr><td align=right>parent:&nbsp;</td><td><a href="?cmd=changeset;node=#node">#rev#:#node#</a></td></tr>"
+changesetparent = "<tr><td class=metatag>parent:</td><td><a href="?cmd=changeset;node=#node#">#rev#:#node#</a></td></tr>"
+filerevparent = "<tr><td class=metatag>parent:</td><td><a href="?cmd=changeset;node=#node#">#rev#:#node#</a></td></tr>"
+fileannotateparent = "<tr><td class=metatag>parent:</td><td><a href="?cmd=changeset;node=#node#">#rev#:#node#</a></td></tr>"