download patch
commit c458a3532584df8a3db552fa252aad34c0fd4425
Author: tri <tri@thac.loan>
Date: Fri Oct 3 14:31:08 2025 +0700
preview image blobs
diff --git a/src/git.zig b/src/git.zig
index b8f227d..c8ebed3 100644
--- a/src/git.zig
+++ b/src/git.zig
pub fn objectType(arena: mem.Allocator, dir: fs.Dir, object_hash: []const u8) !O
return .tree;
}
- std.debug.panic("Unrecognized object type: \"{s}\" - {s}", .{ result, proc.stderr });
+ std.debug.panic("Unrecognized object type: {s} \"{s}\" - {s}", .{
+ object_hash,
+ result,
+ proc.stderr,
+ });
}
/// Replicates git's simple heuristic: if there's a null byte in the first 8k
diff --git a/src/main.zig b/src/main.zig
index 0a2965d..269bc9a 100644
--- a/src/main.zig
+++ b/src/main.zig
pub fn writeCommitsPage(
defer commits_dir.close();
var commits_file = try commits_dir.createFile("index.html", .{});
+ errdefer commits_dir.deleteFile("index.html") catch {};
defer commits_file.close();
var writerBuf: [4096]u8 = undefined;
pub fn writeFilePage(
_ = out_dir.statFile(file_name) catch |err| {
switch (err) {
error.FileNotFound => {
- println(" writing {s}/{s}", .{ constants.web_objects_path, file_name });
+ println(" writing {s}: {s}/{s}", .{
+ args.repo_name,
+ constants.web_objects_path,
+ file_name,
+ });
var file = try out_dir.createFile(file_name, .{});
errdefer out_dir.deleteFile(file_name) catch {};
defer file.close();
pub fn writeFilePage(
args.in_repo_dir,
src_file.hash,
);
- if (git.isBinary(file_content)) {
+
+ if (utils.isImg(src_file.path) and file_content.len <= 1024 * 1024 * 16) {
+ const src_file_name =
+ if (mem.lastIndexOfScalar(u8, src_file.path, '/')) |slash_idx|
+ src_file.path[slash_idx + 1 ..]
+ else
+ src_file.path;
+
+ const blob_file_name = try std.fmt.allocPrint(
+ arena,
+ "{s}.{s}",
+ .{ src_file.hash, src_file_name },
+ );
+
+ // write the blob's actual content next to its html page
+ var blob_file = try out_dir.createFile(blob_file_name, .{});
+ errdefer out_dir.deleteFile(blob_file_name) catch {};
+ defer blob_file.close();
+ try blob_file.writeAll(file_content);
+
+ // write <img> markup in blob page
+ const escaped_file_name = try html.escapeAlloc(arena, src_file_name);
+ try writer.print(
+ \\<img src="{0s}.{1s}" alt="{1s}">
+ \\
+ , .{
+ src_file.hash,
+ escaped_file_name,
+ });
+ } else if (git.isBinary(file_content)) {
try writer.writeAll(
\\<span style="opacity: 0.5">(binary data)</span>
\\
diff --git a/src/utils.zig b/src/utils.zig
index e6a5508..9463deb 100644
--- a/src/utils.zig
+++ b/src/utils.zig
test "humanReadableSize" {
try t.expectEqualStrings("4 TiB", try humanReadableSize(arena, 1024 * 1024 * 1024 * 1024 * 4));
try t.expectEqualStrings("1024 TiB", try humanReadableSize(arena, 1024 * 1024 * 1024 * 1024 * 1024));
}
+
+pub fn isImg(file_path: []const u8) bool {
+ const img_extensions: []const []const u8 = &.{
+ ".apng",
+ ".avif",
+ ".gif",
+ ".jpeg",
+ ".jpg",
+ ".png",
+ ".svg",
+ ".webp",
+ ".bmp",
+ };
+ for (img_extensions) |ext| {
+ if (std.ascii.endsWithIgnoreCase(file_path, ext)) {
+ return true;
+ }
+ }
+ return false;
+}