 git-arr                | 65 ++++++++++++++++++++++++++++++++++---------------
 git.py                 |  5 +++-
 sample.conf            |  7 ++++++
 static/git-arr.css     | 66 ++++++++++++++++++++++++++++++++++++++++----------
 static/git-arr.js      | 10 ++++++++
 utils.py               | 47 ++++++++++++++++++++++++++++++++++-
 views/blob.html        | 10 +++++---
 views/branch.html      |  6 ++---
 views/commit-list.html |  2 +-
 views/commit.html      |  6 ++---
 views/index.html       | 14 +++++------
 views/patch.tpl        |  8 ++++++
 views/summary.html     | 33 ++++++++++++++-----------
 views/tree-list.html   | 16 ++++++++++++
 views/tree.html        | 26 +++++---------------
 15 files changed, 234 insertions(+), 87 deletions(-)

diff --git a/git-arr b/git-arr
index a6d6651..5c4e7db 100755
--- a/git-arr
+++ b/git-arr
@@ -5,10 +5,11 @@ git-arr: A git web html generator.
 
 from __future__ import print_function
 
-import sys
-import os
 import math
 import optparse
+import os
+import re
+import sys
 
 try:
     import configparser
@@ -49,6 +50,7 @@ def load_config(path):
         'rootdiff': 'yes',
         'desc': '',
         'recursive': 'no',
+        'prefix': '',
         'commits_in_summary': '10',
         'commits_per_page': '50',
         'max_pages': '250',
@@ -58,6 +60,8 @@ def load_config(path):
         'git_url_file': 'cloneurl',
         'embed_markdown': 'yes',
         'embed_images': 'no',
+        'ignore': '',
+        'generate_patch': 'yes',
     }
 
     config = configparser.SafeConfigParser(defaults)
@@ -66,28 +70,35 @@ def load_config(path):
     # Do a first pass for general sanity checking and recursive expansion.
     for s in config.sections():
         if config.getboolean(s, 'recursive'):
-            for path in os.listdir(config.get(s, 'path')):
-                fullpath = find_git_dir(config.get(s, 'path') + '/' + path)
+            root = config.get(s, 'path')
+            prefix = config.get(s, 'prefix')
+
+            for path in os.listdir(root):
+                fullpath = find_git_dir(root + '/' + path)
                 if not fullpath:
                     continue
 
                 if os.path.exists(fullpath + '/disable_gitweb'):
                     continue
 
-                if config.has_section(path):
+                section = prefix + path
+                if config.has_section(section):
                     continue
 
-                config.add_section(path)
+                config.add_section(section)
                 for opt, value in config.items(s, raw = True):
-                    config.set(path, opt, value)
+                    config.set(section, opt, value)
 
-                config.set(path, 'path', fullpath)
-                config.set(path, 'recursive', 'no')
+                config.set(section, 'path', fullpath)
+                config.set(section, 'recursive', 'no')
 
             # This recursive section is no longer useful.
             config.remove_section(s)
 
     for s in config.sections():
+        if config.get(s, 'ignore') and re.search(config.get(s, 'ignore'), s):
+            continue
+
         fullpath = find_git_dir(config.get(s, 'path'))
         if not fullpath:
             raise ValueError(
@@ -110,6 +121,7 @@ def load_config(path):
             r.info.max_pages = sys.maxint
         r.info.generate_tree = config.getboolean(s, 'tree')
         r.info.root_diff = config.getboolean(s, 'rootdiff')
+        r.info.generate_patch = config.getboolean(s, 'generate_patch')
 
         r.info.web_url = config.get(s, 'web_url')
         web_url_file = fullpath + '/' + config.get(s, 'web_url_file')
@@ -226,6 +238,19 @@ def commit(repo, cid):
 
     return dict(repo = repo, c=c)
 
+@bottle.route('/r/<repo:repo>/c/<cid:re:[0-9a-f]{5,40}>.patch')
+@bottle.view('patch',
+        # Output is text/plain, don't do HTML escaping.
+        template_settings={"noescape": True})
+def patch(repo, cid):
+    c = repo.commit(cid)
+    if not c:
+        bottle.abort(404, 'Commit not found')
+
+    bottle.response.content_type = 'text/plain; charset=utf8'
+
+    return dict(repo = repo, c=c)
+
 @bottle.route('/r/<repo:repo>/b/<bname:path>/t/f=<fname:path>.html')
 @bottle.route('/r/<repo:repo>/b/<bname:path>/t/<dirname:path>/f=<fname:path>.html')
 @bottle.view('blob')
@@ -284,7 +309,7 @@ def is_404(e):
     else:
         return e.status_code == 404
 
-def generate(output, skip_index = False):
+def generate(output, only = None):
     """Generate static html to the output directory."""
     def write_to(path, func_or_str, args = (), mtime = None):
         path = output + '/' + path
@@ -361,8 +386,8 @@ def generate(output, skip_index = False):
                             (str(r.name), str(bn), oname.raw),
                         tree, (r, bn, oname.url), mtime)
 
-    if not skip_index:
-        write_to('index.html', index())
+    # Always generate the index, to keep the "last updated" time fresh.
+    write_to('index.html', index())
 
     # We can't call static() because it relies on HTTP headers.
     read_f = lambda f: open(f).read()
@@ -373,7 +398,11 @@ def generate(output, skip_index = False):
     write_to('static/syntax.css', read_f, [static_path + '/syntax.css'],
             os.stat(static_path + '/syntax.css').st_mtime)
 
-    for r in sorted(repos.values(), key = lambda r: r.name):
+    rs = sorted(repos.values(), key = lambda r: r.name)
+    if only:
+        rs = [r for r in rs if r.name in only]
+
+    for r in rs:
         write_to('r/%s/index.html' % r.name, summary(r))
         for bn in r.branch_names():
             commit_count = 0
@@ -382,6 +411,8 @@ def generate(output, skip_index = False):
             for cid in commit_ids:
                 write_to('r/%s/c/%s/index.html' % (r.name, cid),
                         commit, (r, cid))
+                if r.info.generate_patch:
+                    write_to('r/%s/c/%s.patch' % (r.name, cid), patch, (r, cid))
                 commit_count += 1
 
             # To avoid regenerating files that have not changed, we will
@@ -441,18 +472,12 @@ def main():
     if not args:
         parser.error('Must specify an action (serve|generate)')
 
-    if opts.only:
-        for rname in list(repos.keys()):
-            if rname not in opts.only:
-                del repos[rname]
-
     if args[0] == 'serve':
         bottle.run(host = 'localhost', port = 8008, reloader = True)
     elif args[0] == 'generate':
         if not opts.output:
             parser.error('Must specify --output')
-        generate(output = opts.output,
-                skip_index = len(opts.only) > 0)
+        generate(output = opts.output, only = opts.only)
     else:
         parser.error('Unknown action %s' % args[0])
 
diff --git a/git.py b/git.py
index 636f3a2..2240175 100644
--- a/git.py
+++ b/git.py
@@ -525,7 +525,10 @@ class Tree:
             cmd.t = None
 
         cmd.arg(self.ref)
-        cmd.arg(path)
+        if not path:
+            cmd.arg(".")
+        else:
+            cmd.arg(path)
 
         for l in cmd.run():
             _mode, otype, _oid, size, name = l.split(None, 4)
diff --git a/sample.conf b/sample.conf
index fb8bbdd..d91f5a7 100644
--- a/sample.conf
+++ b/sample.conf
@@ -67,6 +67,13 @@ path = /srv/git/repo/
 # Default: no
 #embed_images = no
 
+# Ignore repositories that match this regular expression.
+# Generally used with recursive = yes, to ignore repeated repositories (for
+# example, if using symlinks).
+# For ignoring specific repositories, putting a "disable_gitweb" is a much
+# better alternative.
+# Default: empty (don't ignore)
+#ignore = \.git$
 
 # Another repository, we don't generate a tree for it because it's too big.
 [linux]
diff --git a/static/git-arr.css b/static/git-arr.css
index 4e0c7ad..0ef1961 100644
--- a/static/git-arr.css
+++ b/static/git-arr.css
@@ -5,12 +5,10 @@
 
 body {
     font-family: sans-serif;
-    font-size: small;
     padding: 0 1em 1em 1em;
 }
 
 h1 {
-    font-size: x-large;
     background: #ddd;
     padding: 0.3em;
 }
@@ -49,13 +47,11 @@ a.explicit:hover, a.explicit:active {
 /* Normal table, for listing things like repositories, branches, etc. */
 table.nice {
     text-align: left;
-    font-size: small;
 }
 table.nice td {
     padding: 0.15em 0.5em;
 }
 table.nice td.links {
-    font-size: smaller;
 }
 table.nice td.main {
     min-width: 10em;
@@ -69,8 +65,11 @@ table.commits td.date {
     font-style: italic;
     color: gray;
 }
-table.commits td.subject {
-    min-width: 32em;
+
+@media (min-width: 600px) {
+    table.commits td.subject {
+        min-width: 32em;
+    }
 }
 table.commits td.author {
     color: gray;
@@ -100,12 +99,17 @@ span.tag {
     background-color: #ffff88;
 }
 
+/* Projects table */
+table.projects td.name a {
+    color: #038;
+}
+
 /* Age of an object.
  * Note this is hidden by default as we rely on javascript to show it. */
 span.age {
     display: none;
     color: gray;
-    font-size: x-small;
+    font-size: smaller;
 }
 
 span.age-band0 {
@@ -120,6 +124,12 @@ span.age-band2 {
     color: seagreen;
 }
 
+/* Toggable titles */
+div.toggable-title {
+    font-weight: bold;
+    margin-bottom: 0.3em;
+}
+
 /* Commit message and diff. */
 pre.commit-message {
     font-size: large;
@@ -127,7 +137,9 @@ pre.commit-message {
 }
 pre.diff-body {
     /* Note this is only used as a fallback if pygments is not available. */
-    font-size: medium;
+}
+table.changed-files {
+    font-family: monospace;
 }
 table.changed-files span.lines-added {
     color: green;
@@ -146,8 +158,14 @@ div.paginate span.inactive {
 }
 
 /* Directory listing. */
-table.ls td.name {
-    min-width: 20em;
+@media (min-width: 600px) {
+    table.ls td.name {
+        min-width: 20em;
+    }
+}
+table.ls {
+    font-family: monospace;
+    font-size: larger;
 }
 table.ls tr.blob td.size {
     color: gray;
@@ -156,7 +174,6 @@ table.ls tr.blob td.size {
 /* Blob. */
 pre.blob-body {
     /* Note this is only used as a fallback if pygments is not available. */
-    font-size: medium;
 }
 
 table.blob-binary pre {
@@ -178,12 +195,14 @@ table.blob-binary tr.etc {
 /* Pygments overrides. */
 div.linenodiv {
     padding-right: 0.5em;
+    font-size: larger;  /* must match div.source_code */
+}
+div.linenodiv a {
     color: gray;
-    font-size: medium;
 }
 div.source_code {
     background: inherit;
-    font-size: medium;
+    font-size: larger;
 }
 
 /* Repository information table. */
@@ -192,6 +211,10 @@ table.repo_info tr:hover {
 }
 table.repo_info td.category {
     font-weight: bold;
+    /* So we can copy-paste rows and preserve spaces, useful for the row:
+     *   git clone | url
+     */
+    white-space: pre-wrap;
 }
 table.repo_info td {
     vertical-align: top;
@@ -202,3 +225,20 @@ span.ctrlchr {
     padding: 0 0.2ex 0 0.1ex;
     margin:  0 0.2ex 0 0.1ex;
 }
+
+/*
+ * Markdown overrides
+ */
+
+/* Colored links (same as explicit links above) */
+div.markdown a {
+    color: #038;
+}
+div.markdown a:hover, div.markdown a:active {
+    color: #880000;
+}
+
+/* Restrict max width for readability */
+div.markdown {
+    max-width: 55em;
+}
diff --git a/static/git-arr.js b/static/git-arr.js
index d1e3b81..d39ca72 100644
--- a/static/git-arr.js
+++ b/static/git-arr.js
@@ -61,3 +61,13 @@ function replace_timestamps() {
         }
     }
 }
+
+function toggle(id) {
+    var e = document.getElementById(id);
+
+    if (e.style.display == "") {
+        e.style.display = "none"
+    } else if (e.style.display == "none") {
+        e.style.display = ""
+    }
+}
diff --git a/utils.py b/utils.py
index a7d2886..ada9c7e 100644
--- a/utils.py
+++ b/utils.py
@@ -14,12 +14,14 @@ except ImportError:
 
 try:
     import markdown
+    import markdown.treeprocessors
 except ImportError:
     markdown = None
 
 import base64
 import mimetypes
 import string
+import os.path
 
 def shorten(s, width = 60):
     if len(s) < 60:
@@ -97,7 +99,12 @@ def colorize_blob(fname, s):
     return highlight(s, lexer, formatter)
 
 def markdown_blob(s):
-    return markdown.markdown(s)
+    extensions = [
+        "markdown.extensions.fenced_code",
+        "markdown.extensions.tables",
+        RewriteLocalLinksExtension(),
+    ]
+    return markdown.markdown(s, extensions = extensions)
 
 def embed_image_blob(fname, image_data):
     mimetype = mimetypes.guess_type(fname)[0]
@@ -118,3 +125,41 @@ def hexdump(s):
         yield offset, ' '.join(hexvals[:8]), ' '.join(hexvals[8:]), text
         offset += 16
         s = s[16:]
+
+
+if markdown:
+    class RewriteLocalLinks(markdown.treeprocessors.Treeprocessor):
+        """Rewrites relative links to files, to match git-arr's links.
+
+        A link of "[example](a/file.md)" will be rewritten such that it links to
+        "a/f=file.md.html".
+
+        Note that we're already assuming a degree of sanity in the HTML, so we
+        don't re-check that the path is reasonable.
+        """
+        def run(self, root):
+            for child in root:
+                if child.tag == "a":
+                    self.rewrite_href(child)
+
+                # Continue recursively.
+                self.run(child)
+
+        def rewrite_href(self, tag):
+            """Rewrite an <a>'s href."""
+            target = tag.get("href")
+            if not target:
+                return
+            if "://" in target or target.startswith("/"):
+                return
+
+            head, tail = os.path.split(target)
+            new_target = os.path.join(head, "f=" + tail + ".html")
+            tag.set("href", new_target)
+
+
+    class RewriteLocalLinksExtension(markdown.Extension):
+        def extendMarkdown(self, md, md_globals):
+            md.treeprocessors.add(
+                    "RewriteLocalLinks", RewriteLocalLinks(), "_end")
+
diff --git a/views/blob.html b/views/blob.html
index c937b37..58c40a7 100644
--- a/views/blob.html
+++ b/views/blob.html
@@ -1,6 +1,5 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
-    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
+<!DOCTYPE html>
+<html>
 <head>
 
 % if not dirname.raw:
@@ -11,12 +10,13 @@
 % relroot = reltree + '../' * (len(branch.split('/')) - 1)
 
 <title>git &raquo; {{repo.name}} &raquo;
-    {{branch}} &raquo; {{dirname.unicode}}/{{fname.unicode}}</title>
+    {{branch}} &raquo; {{dirname.unicode}}{{fname.unicode}}</title>
 <link rel="stylesheet" type="text/css"
     href="{{relroot}}../../../../../static/git-arr.css"/>
 <link rel="stylesheet" type="text/css"
     href="{{relroot}}../../../../../static/syntax.css"/>
 <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
+<meta name=viewport content="width=device-width, initial-scale=1">
 </head>
 
 <body class="tree">
@@ -73,7 +73,9 @@
 %   end
 </table>
 % elif can_markdown(repo, fname.unicode):
+<div class="markdown">
 {{!markdown_blob(blob.utf8_content)}}
+</div>
 % elif can_colorize(blob.utf8_content):
 {{!colorize_blob(fname.unicode, blob.utf8_content)}}
 % else:
diff --git a/views/branch.html b/views/branch.html
index 0ca6834..799d040 100644
--- a/views/branch.html
+++ b/views/branch.html
@@ -1,6 +1,5 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
-    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
+<!DOCTYPE html>
+<html>
 <head>
 
 % relroot = '../' * (len(branch.split('/')) - 1)
@@ -8,6 +7,7 @@
 <title>git &raquo; {{repo.name}} &raquo; {{branch}}</title>
 <link rel="stylesheet" type="text/css" href="{{relroot}}../../../../static/git-arr.css"/>
 <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
+<meta name=viewport content="width=device-width, initial-scale=1">
 </head>
 
 <body class="branch">
diff --git a/views/commit-list.html b/views/commit-list.html
index 3af9838..94f1dd0 100644
--- a/views/commit-list.html
+++ b/views/commit-list.html
@@ -16,7 +16,7 @@
 %     end
 % end
 
-<table class="nice commits">
+<table class="nice commits" id="commits">
 
 % refs = repo.refs()
 % if not defined("commits"):
diff --git a/views/commit.html b/views/commit.html
index 1ddc4d8..e21ff04 100644
--- a/views/commit.html
+++ b/views/commit.html
@@ -1,11 +1,11 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
-    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
+<!DOCTYPE html>
+<html>
 <head>
 <title>git &raquo; {{repo.name}} &raquo; commit {{c.id[:7]}}</title>
 <link rel="stylesheet" type="text/css" href="../../../../static/git-arr.css"/>
 <link rel="stylesheet" type="text/css" href="../../../../static/syntax.css"/>
 <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
+<meta name=viewport content="width=device-width, initial-scale=1">
 </head>
 
 <body class="commit">
diff --git a/views/index.html b/views/index.html
index 7967a7c..a1d7aa4 100644
--- a/views/index.html
+++ b/views/index.html
@@ -1,17 +1,17 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
-    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
+<!DOCTYPE html>
+<html>
 <head>
 <title>git</title>
 <link rel="stylesheet" type="text/css" href="static/git-arr.css"/>
 <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
-<script src="static/git-arr.js"></script>
+<meta name=viewport content="width=device-width, initial-scale=1">
+<script async src="static/git-arr.js"></script>
 </head>
 
 <body class="index" onload="replace_timestamps()">
 <h1>git</h1>
 
-<table class="nice">
+<table class="nice projects">
     <tr>
         <th>project</th>
         <th>description</th>
@@ -19,8 +19,8 @@
 
     % for repo in sorted(repos.values(), key = lambda r: r.name):
     <tr>
-        <td><a href="r/{{repo.name}}/">{{repo.name}}</a></td>
-        <td><a href="r/{{repo.name}}/">{{repo.info.desc}}</a></td>
+        <td class="name"><a href="r/{{repo.name}}/">{{repo.name}}</a></td>
+        <td class="desc"><a href="r/{{repo.name}}/">{{repo.info.desc}}</a></td>
         <td><span class="age">{{repo.last_commit_timestamp()}}</span></td>
     </tr>
     %end
diff --git a/views/patch.tpl b/views/patch.tpl
new file mode 100644
index 0000000..ab3fca1
--- /dev/null
+++ b/views/patch.tpl
@@ -0,0 +1,8 @@
+From: {{c.author_name}} <{{c.author_email}}>
+Date: {{c.author_date}}
+Subject: {{c.subject}}
+
+{{c.body.strip()}}
+---
+
+{{c.diff.body}}
diff --git a/views/summary.html b/views/summary.html
index c05cca7..d3388e6 100644
--- a/views/summary.html
+++ b/views/summary.html
@@ -1,10 +1,11 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
-    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
+<!DOCTYPE html>
+<html>
 <head>
 <title>git &raquo; {{repo.name}}</title>
 <link rel="stylesheet" type="text/css" href="../../static/git-arr.css"/>
 <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
+<meta name=viewport content="width=device-width, initial-scale=1">
+<script async src="../../static/git-arr.js"></script>
 </head>
 
 <body class="summary">
@@ -25,7 +26,7 @@
 % end
 % if repo.info.git_url:
     <tr>
-        <td class="category">repository</td>
+        <td class="category">git clone </td>
         <td>{{! '<br/>'.join(repo.info.git_url.split())}}</td>
     </tr>
 % end
@@ -35,18 +36,25 @@
 % end
 
 % if "master" in repo.branch_names():
+<div class="toggable-title" onclick="toggle('commits')">
+  <a href="b/master/">commits (master)</a>
+</div>
 %     kwargs = dict(repo = repo, start_ref = "refs/heads/master",
 %                   limit = repo.info.commits_in_summary,
 %                   shorten = shorten, repo_root = ".", offset = 0)
 %     include commit-list **kwargs
 <hr/>
+<div class="toggable-title" onclick="toggle('ls')">
+  <a href="b/master/t/">tree (master)</a>
+</div>
+%     kwargs = dict(repo = repo, tree=repo.tree("master"),
+%                   treeroot="b/master/t", dirname=smstr.from_url(""))
+%     include tree-list **kwargs
+<hr/>
 % end
 
-<table class="nice">
-    <tr>
-        <th>branches</th>
-    </tr>
-
+<div class="toggable-title" onclick="toggle('branches')">branches</div>
+<table class="nice toggable" id="branches">
     % for b in repo.branch_names():
     <tr>
         <td class="main"><a href="b/{{b}}/">{{b}}</a></td>
@@ -62,11 +70,8 @@
 
 % tags = list(repo.tags())
 % if tags:
-<table class="nice">
-    <tr>
-        <th>tags</th>
-    </tr>
-
+<div class="toggable-title" onclick="toggle('tags')">tags</div>
+<table class="nice toggable" id="tags">
     % for name, obj_id in tags:
     <tr>
         <td><a href="c/{{obj_id}}/">{{name}}</a></td>
diff --git a/views/tree-list.html b/views/tree-list.html
new file mode 100644
index 0000000..70f032a
--- /dev/null
+++ b/views/tree-list.html
@@ -0,0 +1,16 @@
+<table class="nice toggable ls" id="ls">
+% key_func = lambda (t, n, s): (t != 'tree', n.raw)
+% for type, name, size in sorted(tree.ls(dirname.raw), key = key_func):
+    <tr class="{{type}}">
+%   if type == "blob":
+        <td class="name"><a href="{{treeroot}}/f={{name.url}}.html">
+            {{!name.html}}</a></td>
+        <td class="size">{{size}}</td>
+%   elif type == "tree":
+        <td class="name">
+            <a class="explicit" href="{{treeroot}}/{{name.url}}/">
+                {{!name.html}}/</a></td>
+%   end
+    </tr>
+% end
+</table>
diff --git a/views/tree.html b/views/tree.html
index 68a5844..3f3829c 100644
--- a/views/tree.html
+++ b/views/tree.html
@@ -1,6 +1,5 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
-    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
+<!DOCTYPE html>
+<html>
 <head>
 
 % if not dirname.raw:
@@ -11,10 +10,11 @@
 % relroot = reltree + '../' * (len(branch.split('/')) - 1)
 
 <title>git &raquo; {{repo.name}} &raquo;
-    {{branch}} &raquo; {{dirname.unicode}}</title>
+    {{branch}} &raquo; {{dirname.unicode if dirname.unicode else '/'}}</title>
 <link rel="stylesheet" type="text/css"
     href="{{relroot}}../../../../../static/git-arr.css"/>
 <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
+<meta name=viewport content="width=device-width, initial-scale=1">
 </head>
 
 <body class="tree">
@@ -36,22 +36,8 @@
 % end
 </h3>
 
-<table class="nice ls">
-% key_func = lambda (t, n, s): (t != 'tree', n.raw)
-% for type, name, size in sorted(tree.ls(dirname.raw), key = key_func):
-    <tr class="{{type}}">
-%   if type == "blob":
-        <td class="name"><a href="./f={{name.url}}.html">
-            {{!name.html}}</a></td>
-        <td class="size">{{size}}</td>
-%   elif type == "tree":
-        <td class="name">
-            <a class="explicit" href="./{{name.url}}/">
-                {{!name.html}}/</a></td>
-%   end
-    </tr>
-% end
-</table>
+% kwargs = dict(repo = repo, tree=tree, treeroot=".")
+% include tree-list **kwargs
 
 </body>
 </html>
