patx/gitman
improve markdown rendering in readmes and comments
Commit 87c5a7f · patx · 2026-05-10T21:39:28Z
Comments
No comments yet.
Diff
diff --git a/app.py b/app.py
index 01bcaa2..dd4a240 100644
--- a/app.py
+++ b/app.py
@@ -900,6 +900,7 @@ def render(template_name, **context):
context.setdefault("error", None)
context.setdefault("notice", None)
context.setdefault("csrf_field", csrf_field)
+ context.setdefault("render_markdown", render_markdown)
context.setdefault("render_markdown_links", render_markdown_links)
context.setdefault("render_repo_description", render_repo_description)
context.setdefault("format_ref_label", format_ref_label)
diff --git a/static/styles.css b/static/styles.css
index ab2bb01..4e35874 100644
--- a/static/styles.css
+++ b/static/styles.css
@@ -314,6 +314,18 @@ button, .button {
.repo-card strong, .repo-card span, .repo-card small, .clone-box code { display: block; }
.markdown-body { overflow-x: auto; }
.markdown-body img { max-width: 100%; }
+.markdown-body code {
+ padding: .12rem .28rem;
+ border-radius: .25rem;
+ background: var(--soft-surface);
+ font: .9em/1.45 ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
+}
+.markdown-body pre code {
+ display: block;
+ padding: 0;
+ background: transparent;
+ font: inherit;
+}
.grid.two { display: grid; grid-template-columns: 1fr 18rem; gap: 2rem; }
.meta-list { display: grid; grid-template-columns: 8rem 1fr; gap: .35rem 1rem; }
.meta-list dt { color: var(--muted); }
@@ -323,8 +335,19 @@ button, .button {
.activity-title, .activity-detail { margin-bottom: .25rem; }
.activity-detail { color: var(--detail); }
.comment-list { display: grid; gap: 1rem; }
-.comment { border-bottom: 1px solid var(--soft-border); }
+.comment { padding-bottom: 1rem; border-bottom: 1px solid var(--soft-border); }
.comment, .activity-feed li { min-width: 0; }
+.comment-meta {
+ display: flex;
+ gap: .5rem;
+ align-items: baseline;
+ margin-bottom: .35rem;
+}
+.comment-body {
+ line-height: 1.6;
+ overflow-wrap: anywhere;
+}
+.comment-body > :last-child { margin-bottom: 0; }
.comment p, .activity-title, .activity-detail {
font-size: 1rem;
line-height: 1.6;
diff --git a/templates/comment.tpl b/templates/comment.tpl
new file mode 100644
index 0000000..1e886a6
--- /dev/null
+++ b/templates/comment.tpl
@@ -0,0 +1,7 @@
+<article class="comment">
+ <header class="comment-meta">
+ <strong><a href="/{{comment["author_username"]}}">@{{comment["author_username"]}}</a></strong>
+ <small class="muted">{{comment["created_at"]}}</small>
+ </header>
+ <div class="comment-body markdown-body">{{!render_markdown(comment["body"])}}</div>
+</article>
diff --git a/templates/commit_detail.tpl b/templates/commit_detail.tpl
index 7686f1c..456cfc5 100644
--- a/templates/commit_detail.tpl
+++ b/templates/commit_detail.tpl
@@ -34,9 +34,7 @@
% if comments:
<div class="comment-list">
% for comment in comments:
- <article class="comment">
- <p><strong><a href="/{{comment["author_username"]}}">@{{comment["author_username"]}}</a>:</strong> {{!render_markdown_links(comment["body"])}} <small class="muted">{{comment["created_at"]}}</small></p>
- </article>
+ % include("comment.tpl", comment=comment)
% end
</div>
% else:
diff --git a/templates/issue_detail.tpl b/templates/issue_detail.tpl
index 3e452b6..c374059 100644
--- a/templates/issue_detail.tpl
+++ b/templates/issue_detail.tpl
@@ -41,9 +41,7 @@
% if comments:
<div class="comment-list">
% for comment in comments:
- <article class="comment">
- <p><strong><a href="/{{comment["author_username"]}}">@{{comment["author_username"]}}</a>:</strong> {{!render_markdown_links(comment["body"])}} <small class="muted">{{comment["created_at"]}}</small></p>
- </article>
+ % include("comment.tpl", comment=comment)
% end
</div>
% else:
diff --git a/templates/pull_request_detail.tpl b/templates/pull_request_detail.tpl
index 8fddd93..8c0fd47 100644
--- a/templates/pull_request_detail.tpl
+++ b/templates/pull_request_detail.tpl
@@ -48,9 +48,7 @@
% if comments:
<div class="comment-list">
% for comment in comments:
- <article class="comment">
- <p><strong><a href="/{{comment["author_username"]}}">@{{comment["author_username"]}}</a>:</strong> {{!render_markdown_links(comment["body"])}} <small class="muted">{{comment["created_at"]}}</small></p>
- </article>
+ % include("comment.tpl", comment=comment)
% end
</div>
% else:
diff --git a/tests/test_app.py b/tests/test_app.py
index 982fbfa..2a8ab64 100644
--- a/tests/test_app.py
+++ b/tests/test_app.py
@@ -449,6 +449,12 @@ def test_render_markdown_strips_scripts_and_unsafe_links():
| A |
| - |
| B |
+
+Inline `print('code')`.
+
+```
+print('block')
+```
"""
)
@@ -457,6 +463,8 @@ def test_render_markdown_strips_scripts_and_unsafe_links():
assert "javascript:" not in rendered.lower()
assert 'href="https://example.com"' in rendered
assert "<table>" in rendered
+ assert "<code>print('code')</code>" in rendered
+ assert "<pre><code>print('block')" in rendered
def test_render_markdown_links_allows_only_links():
@@ -2255,9 +2263,14 @@ def test_bottle_issue_routes_create_comment_close_and_reopen(isolated_app):
assert response.status_code == 200
assert "Comment body is required." in response.text
- response = client.post("/alice/demo/issues/1", {"action": "comment", "body": "I can reproduce this"})
+ comment_body = "I can reproduce this\n\n`print('code')`\n\n```\nprint('block')\n```"
+ response = client.post("/alice/demo/issues/1", {"action": "comment", "body": comment_body})
assert response.status_code == 303
- assert "I can reproduce this" in client.get("/alice/demo/issues/1").text
+ issue_response = client.get("/alice/demo/issues/1")
+ assert "I can reproduce this" in issue_response.text
+ assert 'class="comment-body markdown-body"' in issue_response.text
+ assert "<code>print('code')</code>" in issue_response.text
+ assert "<pre><code>print('block')" in issue_response.text
response = client.post("/alice/demo/issues/1", {"action": "close"})
assert response.status_code == 303