commit 247964f25c4904d31451176723b335de725ff297
Author: tri <tri@thac.loan>
Date:   Mon Sep 29 08:50:15 2025 +0700

    clumsily escape commit subject
    
    I should really look into using either a builder or templates.

diff --git a/src/html.zig b/src/html.zig
index 50eafb5..ceaaa2e 100644
--- a/src/html.zig
+++ b/src/html.zig
@@ -1,10 +1,13 @@
 const std = @import("std");
 const t = std.testing;
 
-pub fn escape(
-    out: *std.Io.Writer,
-    text: []const u8,
-) !void {
+pub fn escapeBuf(buf: *[]u8, text: []const u8) ![]const u8 {
+    var w = std.Io.Writer.fixed(buf);
+    try escape(&w, text);
+    return w.buffered();
+}
+
+pub fn escape(out: *std.Io.Writer, text: []const u8) !void {
     for (text) |char| {
         switch (char) {
             '&' => try out.writeAll("&amp;"),
diff --git a/src/main.zig b/src/main.zig
index 23bae57..1f2c606 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -3,6 +3,7 @@ const fs = std.fs;
 const mem = std.mem;
 const println = @import("utils.zig").println;
 const git = @import("git.zig");
+const html = @import("html.zig");
 
 const web_prefix = "-";
 
@@ -275,7 +276,12 @@ pub fn writeRepoPage(args: RepoArgs) !void {
             try std.fmt.bufPrint(&buf, "{s}/{s}", .{ repo_name, git_dir_path }),
     });
 
+    var escapeBuf: [1024]u8 = undefined;
     for (commits) |cmt| {
+        var escapeWriter = std.Io.Writer.fixed(&escapeBuf);
+        try html.escape(&escapeWriter, cmt.subject[0..@min(cmt.subject.len, 80)]);
+        const escaped_subject = escapeWriter.buffered();
+
         try writer.interface.print(
             \\<tr>
             \\  <td class="monospace" title="commit diff coming Soon™">{0s}</td>
@@ -287,7 +293,7 @@ pub fn writeRepoPage(args: RepoArgs) !void {
             .{
                 //cmt.hash,
                 cmt.hash[0..10],
-                cmt.subject[0..@min(cmt.subject.len, 80)],
+                escaped_subject,
                 if (cmt.subject.len > 80) "…" else "",
                 cmt.time,
             },