[PATCH 1/2] css and patch view updates

Nate Case ncase at xes-inc.com
Fri Nov 7 10:49:35 EST 2008


From: Peter Tyser <ptyser at xes-inc.com>

The gitweb.css file from kernel.org was integrated into patchwork
to provide a similar interface style to the standard gitweb interface.

The ordering of comments and patches was also updated for the patch view.
The patch commit message is displayed first, followed by the patch contents,
followed by comments (if any are present) in chronological order. The
ordering is meant to reflect a patch submission/discussion utilizing bottom
posting email responses.

SQL/python migration scripts are also included to move the first
comment (the patch log message) to the newly created log_msg field.

Signed-off-by: Peter Tyser <ptyser at xes-inc.com>
Signed-off-by: Nate Case <ncase at xes-inc.com>
---
 apps/patchwork/bin/log_msg.py         |   39 +++
 apps/patchwork/bin/parsemail.py       |    8 +-
 apps/patchwork/models.py              |   11 +-
 apps/patchwork/templatetags/syntax.py |   58 +++--
 htdocs/css/gitweb.css                 |  465 +++++++++++++++++++++++++++++++++
 htdocs/css/style.css                  |   34 +--
 lib/sql/migration/003-add-log_msg.sql |    3 +
 templates/base.html                   |    8 +-
 templates/patchwork/patch.html        |   62 +++--
 9 files changed, 599 insertions(+), 89 deletions(-)
 create mode 100755 apps/patchwork/bin/log_msg.py
 create mode 100644 htdocs/css/gitweb.css
 create mode 100644 lib/sql/migration/003-add-log_msg.sql

diff --git a/apps/patchwork/bin/log_msg.py b/apps/patchwork/bin/log_msg.py
new file mode 100755
index 0000000..8a2d6e4
--- /dev/null
+++ b/apps/patchwork/bin/log_msg.py
@@ -0,0 +1,39 @@
+#!/usr/bin/python
+#
+# Patchwork - automated patch tracking system
+# Copyright (C) 2008 Jeremy Kerr <jk at ozlabs.org>
+#
+# This file is part of the Patchwork package.
+#
+# Patchwork is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# Patchwork is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Patchwork; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+from patchwork.models import Patch, Comment
+import sys
+
+if __name__ == '__main__':
+    if len(sys.argv) > 1:
+        patches = Patch.objects.filter(id__in = sys.argv[1:])
+    else:
+        patches = Patch.objects.all()
+
+    for patch in patches:
+        print patch.id, patch.name
+        if not patch.log_msg:
+            # Find first comment matching this patch
+            comment = Comment.objects.filter(patch = patch)[0]
+            patch.log_msg = comment.content
+            patch.save()
+            print "Deleting comment #%d" % comment.id
+            comment.delete()
diff --git a/apps/patchwork/bin/parsemail.py b/apps/patchwork/bin/parsemail.py
index 7f6727f..995b59f 100755
--- a/apps/patchwork/bin/parsemail.py
+++ b/apps/patchwork/bin/parsemail.py
@@ -165,11 +165,11 @@ def find_content(project, mail):
 
     if patchbuf:
         mail_headers(mail)
-	name = clean_subject(mail.get('Subject'), [project.linkname])
+        name = clean_subject(mail.get('Subject'), [project.linkname])
         patch = Patch(name = name, content = patchbuf,
-                    date = mail_date(mail), headers = mail_headers(mail))
-
-    if commentbuf:
+                    date = mail_date(mail), headers = mail_headers(mail),
+                    log_msg = clean_content(commentbuf))
+    elif commentbuf:
         if patch:
             cpatch = patch
         else:
diff --git a/apps/patchwork/models.py b/apps/patchwork/models.py
index 91c0f97..91eb2f1 100644
--- a/apps/patchwork/models.py
+++ b/apps/patchwork/models.py
@@ -189,6 +189,7 @@ class Patch(models.Model):
     content = models.TextField()
     commit_ref = models.CharField(max_length=255, null = True, blank = True)
     hash = HashField(null = True, db_index = True)
+    log_msg = models.TextField(blank = True)
 
     def __str__(self):
         return self.name
@@ -227,15 +228,7 @@ class Patch(models.Model):
         return str.strip('-') + '.patch'
 
     def mbox(self):
-        comment = None
-        try:
-            comment = Comment.objects.get(patch = self, msgid = self.msgid)
-        except Exception:
-            pass
-
-        body = ''
-        if comment:
-            body = comment.content.strip() + "\n"
+        body = self.log_msg.strip() + "\n"
 
         responses = False
         for comment in Comment.objects.filter(patch = self) \
diff --git a/apps/patchwork/templatetags/syntax.py b/apps/patchwork/templatetags/syntax.py
index a538062..dc55ee0 100644
--- a/apps/patchwork/templatetags/syntax.py
+++ b/apps/patchwork/templatetags/syntax.py
@@ -28,45 +28,61 @@ def _compile(t):
     (r, str) = t
     return (re.compile(r, re.M | re.I), str)
 
-_patch_span_res = map(_compile, [
-        ('^(Index:?|diff|\-\-\-|\+\+\+|\*\*\*) .*$', 'p_header'),
-        ('^\+.*$', 'p_add'),
-        ('^-.*$', 'p_del'),
-        ('^!.*$', 'p_mod'),
+_patch_res = map(_compile, [
+        ('^\+\+\+ .*$', 'diff to_file'),
+        ('^\-\-\- .*$', 'diff from_file'),
+        ('^Index:? .*$', 'diff extended_header'),
+        ('^diff \-\-.*$', 'diff header'),
+        ('^\+.*$', 'diff add'),
+        ('^-.*$', 'diff rem'),
         ])
 
-_patch_chunk_re = \
+_chunk_re = \
         re.compile('^(@@ \-\d+(?:,\d+)? \+\d+(?:,\d+)? @@)(.*)$', re.M | re.I)
 
-_comment_span_res = map(_compile, [
-        ('^\s*Signed-off-by: .*$', 'signed-off-by'),
-        ('^\s*Acked-by: .*$', 'acked-by'),
-        ('^\s*From: .*$', 'from'),
+_comment_res = map(_compile, [
+        ('^\s*Signed-off-by: .*$', 'signoff'),
+        ('^\s*Acked-by: .*$', 'signoff'),
+        ('^\s*cc: .*$', 'signoff'),
         ('^\s*&gt;.*$', 'quote'),
         ])
 
+_non_div_re = \
+        re.compile('^(?!\<div)(.*)$', re.M | re.I)
+
+_non_span_re = \
+        re.compile('^(?!\<span)(.*)$', re.M | re.I)
+
+_line_re = \
+        re.compile('^(.*)$', re.M | re.I)
+
+_div = '<div class="%s">%s</div>'
 _span = '<span class="%s">%s</span>'
 
 @register.filter
-def patchsyntax(patch):
-    content = escape(patch.content)
+def patchsyntax(content):
+    content = escape(content)
 
-    for (r,cls) in _patch_span_res:
-        content = r.sub(lambda x: _span % (cls, x.group(0)), content)
+    for (r,cls) in _patch_res:
+        content = r.sub(lambda x: _div % (cls, x.group(0)), content)
 
-    content = _patch_chunk_re.sub( \
+    content = _chunk_re.sub( \
             lambda x: \
-                _span % ('p_chunk', x.group(1)) + ' ' + \
-                _span % ('p_context', x.group(2)), \
-            content)
+                _div % ('diff chunk_header', x.group(1) + \
+                ' <span class="chunk_info">' + x.group(2) + \
+                ' </span>'), content)
+
+    content = _non_div_re.sub(lambda x: _div % ('diff', x.group(1)), content)
 
     return mark_safe(content)
 
 @register.filter
-def commentsyntax(comment):
-    content = escape(comment.content)
+def commentsyntax(content):
+    content = escape(content)
 
-    for (r,cls) in _comment_span_res:
+    for (r,cls) in _comment_res:
         content = r.sub(lambda x: _span % (cls, x.group(0)), content)
 
+    content = _line_re.sub(lambda x: x.group(0) + '<br>', content)
+
     return mark_safe(content)
diff --git a/htdocs/css/gitweb.css b/htdocs/css/gitweb.css
new file mode 100644
index 0000000..7177c6e
--- /dev/null
+++ b/htdocs/css/gitweb.css
@@ -0,0 +1,465 @@
+body {
+	font-family: sans-serif;
+	font-size: 12px;
+	border: solid #d9d8d1;
+	border-width: 1px;
+	margin: 10px;
+	background-color: #ffffff;
+	color: #000000;
+}
+
+a {
+	color: #0000cc;
+}
+
+a:hover, a:visited, a:active {
+	color: #880000;
+}
+
+span.cntrl {
+	border: dashed #aaaaaa;
+	border-width: 1px;
+	padding: 0px 2px 0px 2px;
+	margin:  0px 2px 0px 2px;
+}
+
+img.logo {
+	float: right;
+	border-width: 0px;
+}
+
+div.page_header {
+	height: 25px;
+	padding: 8px;
+	font-size: 18px;
+	font-weight: bold;
+	background-color: #d9d8d1;
+}
+
+div.page_header a:visited, a.header {
+	color: #0000cc;
+}
+
+div.page_header a:hover {
+	color: #880000;
+}
+
+div.page_nav {
+	padding: 8px;
+}
+
+div.page_nav a:visited {
+	color: #0000cc;
+}
+
+div.page_path {
+	padding: 8px;
+	font-weight: bold;
+	border: solid #d9d8d1;
+	border-width: 0px 0px 1px;
+}
+
+div.page_footer {
+	height: 17px;
+	padding: 4px 8px;
+	background-color: #d9d8d1;
+}
+
+div.page_footer_text {
+	float: left;
+	color: #555555;
+	font-style: italic;
+}
+
+div.page_body {
+	padding: 8px;
+	font-family: monospace;
+}
+
+div.title, a.title {
+	display: block;
+	padding: 6px 8px;
+	font-weight: bold;
+	background-color: #edece6;
+	text-decoration: none;
+	color: #000000;
+}
+
+a.title:hover {
+	background-color: #d9d8d1;
+}
+
+div.title_text {
+	padding: 6px 0px;
+	border: solid #d9d8d1;
+	border-width: 0px 0px 1px;
+	font-family: monospace;
+}
+
+div.log_body {
+	padding: 8px 8px 8px 150px;
+}
+
+span.age {
+	position: relative;
+	float: left;
+	width: 142px;
+	font-style: italic;
+}
+
+div.page_body span.signoff {
+	color: #888888;
+}
+
+div.log_link {
+	padding: 0px 8px;
+	font-size: 10px;
+	font-family: sans-serif;
+	font-style: normal;
+	position: relative;
+	float: left;
+	width: 136px;
+}
+
+div.list_head {
+	padding: 6px 8px 4px;
+	border: solid #d9d8d1;
+	border-width: 1px 0px 0px;
+	font-style: italic;
+}
+
+div.author_date {
+	padding: 8px;
+	border: solid #d9d8d1;
+	border-width: 0px 0px 1px 0px;
+	font-style: italic;
+}
+
+a.list {
+	text-decoration: none;
+	color: #000000;
+}
+
+a.subject, a.name {
+	font-weight: bold;
+}
+
+table.tags a.subject {
+	font-weight: normal;
+}
+
+a.list:hover {
+	text-decoration: underline;
+	color: #880000;
+}
+
+a.text {
+	text-decoration: none;
+	color: #0000cc;
+}
+
+a.text:visited {
+	text-decoration: none;
+	color: #880000;
+}
+
+a.text:hover {
+	text-decoration: underline;
+	color: #880000;
+}
+
+table {
+	padding: 8px 4px;
+}
+
+table.project_list {
+	border-spacing: 0;
+}
+
+table.diff_tree {
+	border-spacing: 0;
+	font-family: monospace;
+}
+
+table.blame {
+	border-collapse: collapse;
+}
+
+table.blame td {
+	padding: 0px 5px;
+	font-size: 12px;
+	vertical-align: top;
+}
+
+th {
+	padding: 2px 5px;
+	font-size: 12px;
+	text-align: left;
+}
+
+tr.light:hover {
+	background-color: #edece6;
+}
+
+tr.dark {
+	background-color: #f6f6f0;
+}
+
+tr.dark2 {
+	background-color: #f6f6f0;
+}
+
+tr.dark:hover {
+	background-color: #edece6;
+}
+
+td {
+	padding: 2px 5px;
+	font-size: 12px;
+	vertical-align: top;
+}
+
+td.link, td.selflink {
+	padding: 2px 5px;
+	font-family: sans-serif;
+	font-size: 10px;
+}
+
+td.selflink {
+	padding-right: 0px;
+}
+
+td.sha1 {
+	font-family: monospace;
+}
+
+td.error {
+	color: red;
+	background-color: yellow;
+}
+
+td.current_head {
+	text-decoration: underline;
+}
+
+table.diff_tree span.file_status.new {
+	color: #008000;
+}
+
+table.diff_tree span.file_status.deleted {
+	color: #c00000;
+}
+
+table.diff_tree span.file_status.moved,
+table.diff_tree span.file_status.mode_chnge {
+	color: #777777;
+}
+
+table.diff_tree span.file_status.copied {
+  color: #70a070;
+}
+
+/* age2: 60*60*24*2 <= age */
+table.project_list td.age2, table.blame td.age2 {
+	font-style: italic;
+}
+
+/* age1: 60*60*2 <= age < 60*60*24*2 */
+table.project_list td.age1 {
+	color: #009900;
+	font-style: italic;
+}
+
+table.blame td.age1 {
+	color: #009900;
+	background: transparent;
+}
+
+/* age0: age < 60*60*2 */
+table.project_list td.age0 {
+	color: #009900;
+	font-style: italic;
+	font-weight: bold;
+}
+
+table.blame td.age0 {
+	color: #009900;
+	background: transparent;
+	font-weight: bold;
+}
+
+td.pre, div.pre, div.diff {
+	font-family: monospace;
+	font-size: 12px;
+	white-space: pre;
+}
+
+td.mode {
+	font-family: monospace;
+}
+
+/* styling of diffs (patchsets): commitdiff and blobdiff views */
+div.diff.header,
+div.diff.extended_header {
+	white-space: normal;
+}
+
+div.diff.header {
+	font-weight: bold;
+
+	background-color: #edece6;
+
+	margin-top: 4px;
+	padding: 4px 0px 2px 0px;
+	border: solid #d9d8d1;
+	border-width: 1px 0px 1px 0px;
+}
+
+div.diff.header a.path {
+	text-decoration: underline;
+}
+
+div.diff.extended_header,
+div.diff.extended_header a.path,
+div.diff.extended_header a.hash {
+	color: #777777;
+}
+
+div.diff.extended_header .info {
+	color: #b0b0b0;
+}
+
+div.diff.extended_header {
+	background-color: #f6f5ee;
+	padding: 2px 0px 2px 0px;
+}
+
+div.diff a.list,
+div.diff a.path,
+div.diff a.hash {
+	text-decoration: none;
+}
+
+div.diff a.list:hover,
+div.diff a.path:hover,
+div.diff a.hash:hover {
+	text-decoration: underline;
+}
+
+div.diff.to_file a.path,
+div.diff.to_file {
+	color: #007000;
+}
+
+div.diff.add {
+	color: #008800;
+}
+
+div.diff.from_file a.path,
+div.diff.from_file {
+	color: #aa0000;
+}
+
+div.diff.rem {
+	color: #cc0000;
+}
+
+div.diff.chunk_header a,
+div.diff.chunk_header {
+	color: #990099;
+}
+
+div.diff.chunk_header {
+	border: dotted #ffe0ff;
+	border-width: 1px 0px 0px 0px;
+	margin-top: 2px;
+}
+
+div.diff.chunk_header span.chunk_info {
+	background-color: #ffeeff;
+}
+
+div.diff.chunk_header span.section {
+	color: #aa22aa;
+}
+
+div.diff.incomplete {
+	color: #cccccc;
+}
+
+
+div.index_include {
+	border: solid #d9d8d1;
+	border-width: 0px 0px 1px;
+	padding: 12px 8px;
+}
+
+div.search {
+	font-size: 12px;
+	font-weight: normal;
+	margin: 4px 8px;
+	position: absolute;
+	top: 56px;
+	right: 12px
+}
+
+td.linenr {
+	text-align: right;
+}
+
+a.linenr {
+	color: #999999;
+	text-decoration: none
+}
+
+a.rss_logo {
+	float: right;
+	padding: 3px 0px;
+	width: 35px;
+	line-height: 10px;
+	border: 1px solid;
+	border-color: #fcc7a5 #7d3302 #3e1a01 #ff954e;
+	color: #ffffff;
+	background-color: #ff6600;
+	font-weight: bold;
+	font-family: sans-serif;
+	font-size: 10px;
+	text-align: center;
+	text-decoration: none;
+}
+
+a.rss_logo:hover {
+	background-color: #ee5500;
+}
+
+span.refs span {
+	padding: 0px 4px;
+	font-size: 10px;
+	font-weight: normal;
+	border: 1px solid;
+	background-color: #ffaaff;
+	border-color: #ffccff #ff00ee #ff00ee #ffccff;
+}
+
+span.refs span.ref {
+	background-color: #aaaaff;
+	border-color: #ccccff #0033cc #0033cc #ccccff;
+}
+
+span.refs span.tag {
+	background-color: #ffffaa;
+	border-color: #ffffcc #ffee00 #ffee00 #ffffcc;
+}
+
+span.refs span.head {
+	background-color: #aaffaa;
+	border-color: #ccffcc #00cc33 #00cc33 #ccffcc;
+}
+
+span.atnight {
+	color: #cc0000;
+}
+
+span.match {
+	color: #e00000;
+}
diff --git a/htdocs/css/style.css b/htdocs/css/style.css
index 4d1e440..c17d088 100644
--- a/htdocs/css/style.css
+++ b/htdocs/css/style.css
@@ -51,7 +51,7 @@ body {
 #nav {
 	float: left
 	width: 100%;
-	background: #e8e8e8;
+	background-color: #d9d8d1;
 	border-bottom: 0.2em solid #786fb4;
 	font-size: 90%;
 	padding: 0.2em 0.5em;
@@ -148,7 +148,7 @@ table.patchlist td img {
 }
 
 table.patchlist td.patchlistfilters {
-	background: #c0c0ff;
+	background: #d9d8d1;
 	border-top: thin solid gray;
 	border-bottom: thin solid black;
 	font-size: smaller;
@@ -247,36 +247,15 @@ table.patchmeta tr th, table.patchmeta tr td {
 	background: #f0f0f0;
 }
 
-.patch .content {
+.content {
 	border: thin solid gray;
-	padding: 1em;
+	padding: 0em;
 }
 
 .quote {
 	color: #007f00;
 }
 
-span.p_header	{ color: #2e8b57; font-weight: bold; }
-span.p_chunk	{ color: #a52a2a; font-weight: bold; }
-span.p_context	{ color: #a020f0; }
-span.p_add	{ color: #008b8b; }
-span.p_del	{ color: #6a5acd; }
-span.p_mod	{ color: #0000ff; }
-
-.acked-by {
-	color: #2d4566;
-
-}
-
-.signed-off-by {
-	color: #672d45;
-	font-weight: bold;
-}
-
-.from {
-	font-weight: bold;
-}
-
 /* bundles */
 table.bundlelist {
 	margin-top: 2em;
@@ -314,9 +293,10 @@ div.patchform h3 {
 	margin-right: -0.6em;
 	padding-left: 0.3em;
 	padding-right: 0.3em;
-	background: #786fb4;
-	color: white;
+	background: #d9d8d1;
+	color: black;
 	font-size: 100%;
+	border-bottom: thin solid gray;
 }
 
 div.patchform ul {
diff --git a/lib/sql/migration/003-add-log_msg.sql b/lib/sql/migration/003-add-log_msg.sql
new file mode 100644
index 0000000..a56d9ba
--- /dev/null
+++ b/lib/sql/migration/003-add-log_msg.sql
@@ -0,0 +1,3 @@
+BEGIN;
+ALTER TABLE patchwork_patch ADD COLUMN log_msg text;
+COMMIT;
diff --git a/templates/base.html b/templates/base.html
index c6a5b03..1e4aecd 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -4,6 +4,7 @@
  <head>
   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
   <title>{% block title %}Patchwork{% endblock %} - Patchwork</title>
+  <link rel="stylesheet" type="text/css" href="/css/gitweb.css"/>
   <link rel="stylesheet" type="text/css" href="/css/style.css"/>
   <script language="JavaScript" type="text/javascript" src="/js/common.js">
   </script>
@@ -74,10 +75,9 @@
 {% block body %}
 {% endblock %}
   </div>
-  <div id="footer">
-   <a href="http://ozlabs.org/~jk/projects/patchwork">patchwork</a>
-   patch tracking system
-  </div>
+  <div class="page_footer">
+   <div class="page_footer_text"><a href="http://ozlabs.org/~jk/projects/patchwork">patchwork</a> patch tracking system</div>
+   </div>
  </body>
 </html>
 
diff --git a/templates/patchwork/patch.html b/templates/patchwork/patch.html
index 7c249ec..ae95af7 100644
--- a/templates/patchwork/patch.html
+++ b/templates/patchwork/patch.html
@@ -28,19 +28,19 @@ function toggle_headers(link_id, headers_id)
 </script>
 
 <table class="patchmeta">
- <tr>
+ <tr class="dark">
   <th>Submitter</th>
   <td>{{ patch.submitter|personify }}</td></tr>
  </tr>
- <tr>
+ <tr class="light">
   <th>Date</th>
   <td>{{ patch.date }}</td>
  </tr>
- <tr>
+ <tr class="dark">
   <th>Message ID</th>
   <td>{{ patch.msgid }}</td>
  </tr>
- <tr>
+ <tr class="light">
   <th>Download</th>
   <td>
    <a href="{% url patchwork.views.patch.mbox patch_id=patch.id %}"
@@ -49,27 +49,27 @@ function toggle_headers(link_id, headers_id)
    >patch</a>
    </td>
  </tr>
- <tr>
+ <tr class="dark">
   <th>Permalink</th>
   <td><a href="{{ patch.get_absolute_url }}">{{ patch.get_absolute_url }}</a>
  </tr>
-  <tr>
+ <tr class="light">
    <th>State</td>
    <td>{{ patch.state.name }}{% if patch.archived %}, archived{% endif %}</td>
   </tr>
 {% if patch.commit_ref %}
-  <tr>
+  <tr class="dark">
    <th>Commit</td>
    <td>{{ patch.commit_ref }}</td>
   </tr>
 {% endif %}
 {% if patch.delegate %}
-  <tr>
+  <tr class="light">
    <th>Delegated to:</td>
    <td>{{ patch.delegate.get_profile.name }}</td>
   </tr>
 {% endif %}
- <tr>
+ <tr class="dark">
   <th>Headers</th>
   <td><a id="togglepatchheaders"
    href="javascript:toggle_headers('togglepatchheaders', 'patchheaders')"
@@ -200,21 +200,35 @@ function toggle_headers(link_id, headers_id)
 
 
 
-<h2>Comments</h2>
-{% for comment in patch.comments %}
-<div class="comment">
-<div class="meta">{{ comment.submitter|personify }} - {{comment.date}}</div>
-<pre class="content">
-{{ comment|commentsyntax }}
-</pre>
-</div>
-{% endfor %}
-
-<h2>Patch</h2>
-<div class="patch">
-<pre class="content">
-{{ patch|patchsyntax }}
-</pre>
+<br>
+<div class="content">
+<div class="page_header">Patch:</div>
+<div class="title">{{patch.name}}</div>
+  <div class="comment">
+   <div class="author_date">
+    {{ patch.submitter|personify }} - {{ patch.date }}
+   </div>
+   {% if patch.log_msg %}
+    <div class="page_body">
+     {{ patch.log_msg|commentsyntax }}
+    </div>
+   {% endif %}
+  </div>
+ {{ patch.content|patchsyntax }}
 </div>
 
+{% if patch.comments %}
+ <br>
+ <div class="content">
+  <div class="page_header">Comments</div>
+  {% for comment in patch.comments %}
+   <div class="comment">
+    <div class="title">{{ comment.submitter|personify }} - {{comment.date}}</div>
+    <div class="page_body">
+     {{ comment.content|commentsyntax }}
+    </div>
+   </div>
+  {% endfor %}
+ </div>
+{% endif %}
 {% endblock %}
-- 
1.5.5.1




More information about the Patchwork mailing list