size: 4 KiB
const std = @import("std"); const mem = std.mem; const Io = std.Io; const fmt = std.fmt; const html = @import("html.zig"); const utils = @import("utils.zig"); const constants = @import("constants.zig"); pub const Crumb = struct { href: ?[]const u8 = null, text: []const u8, }; pub const BaseArgs = struct { title: ?[]const u8 = null, breadcrumbs: []const Crumb, }; // Remember to close with base_end() pub fn base_start(arena: mem.Allocator, writer: *Io.Writer, args: BaseArgs) !void { try writer.print( \\<!doctype html> \\<html lang="en"> \\ <head> \\ <meta charset="utf-8" /> \\ <title>{0s}</title> \\ <meta name="viewport" content="width=device-width, initial-scale=1.0" /> \\ <link rel="stylesheet" href="/_/_khoe-hang/style.css"> \\ <script src="/_/_khoe-hang/script.js"></script> \\ </head> \\ <body> \\ <header> \\ <div id="breadcrumbs"> \\ / , .{ if (args.title) |title| try html.escapeAlloc( arena, try fmt.allocPrint(arena, "{s} | khoe", .{title}), ) else "khoe", }); for (args.breadcrumbs) |crumb| { const escaped_text = try html.escapeAlloc(arena, crumb.text); if (crumb.href) |href| { try writer.print( \\<a href="{0s}">{1s}</a>/ , .{ href, escaped_text }); } else { try writer.print( \\<span>{0s}</span> , .{escaped_text}); } } try writer.writeAll( \\ </div> \\ </header> \\ ); } pub fn base_end(writer: *Io.Writer) !void { try writer.writeAll( \\ </body> \\</html> \\ ); } pub fn repo_metadata(arena: mem.Allocator, writer: *Io.Writer, args: struct { description: []const u8, repo_size: u64, commit_count: usize, site_url: [*:0]const u8, repo_name: []const u8, git_dir_path: []const u8, }) !void { const clone_path = if (mem.eql(u8, args.git_dir_path, ".")) args.repo_name else try std.fmt.allocPrint( arena, "{s}/{s}", .{ args.repo_name, args.git_dir_path }, ); try writer.print( \\ <p style="margin:0; font-style:italic;">{0s}</p> \\ <p style="margin:0">{1s} | {2d} commits</p> \\ \\ <pre class="git-clone-command">git clone {3s}/{4s}</pre> \\ , .{ try html.escapeAlloc(arena, args.description), try utils.humanReadableSize(arena, args.repo_size), args.commit_count, args.site_url, clone_path, }, ); } pub fn repo_nav( writer: *Io.Writer, args: struct { repo_name: []const u8, active: enum { source, readme, commits }, readme_filename: ?[]const u8, }, ) !void { try writer.writeAll( \\<nav class="repo-nav"> \\ <ul> \\ ); const source_class = if (args.active == .source) "active" else ""; const readme_class = if (args.active == .readme) "active" else ""; const commits_class = if (args.active == .commits) "active" else ""; try writer.print( \\ <li class="{0s}"><a href="/{1s}/{2s}/">source</a></li> \\ , .{ source_class, constants.web_path, args.repo_name, }); if (args.readme_filename) |fname| { try writer.print( \\ <li class="{0s}"><a href="/{1s}/{2s}/{3s}/">{4s}</a></li> \\ , .{ readme_class, constants.web_path, args.repo_name, constants.web_readme_path, fname, }); } try writer.print( \\ <li class="{0s}"><a href="/{1s}/{2s}/{3s}">commits</a></li> \\ , .{ commits_class, constants.web_path, args.repo_name, constants.web_commits_path, }); try writer.writeAll( \\ </ul> \\</nav> \\ ); } pub fn repo_content_start(writer: *Io.Writer) !void { try writer.writeAll( \\<div class="repo-content"> \\ ); } pub fn repo_content_end(writer: *Io.Writer) !void { try writer.writeAll( \\</div> \\ ); }