diff options
| author | Robert Günzler <r@gnzler.io> | 2025-01-07 14:50:08 +0100 |
|---|---|---|
| committer | Robert Günzler <r@gnzler.io> | 2025-01-07 15:49:52 +0100 |
| commit | 64b42058dbf7fa1a40d95265ff3f75a0b604c8d8 (patch) | |
| tree | 8886d06ad8e6b569cb50ebb7a8ef9c29f5c07bb0 | |
| parent | 56951dd8a3ab52a881f244381b72a1d5701f3bb4 (diff) | |
| download | site-64b42058dbf7fa1a40d95265ff3f75a0b604c8d8.tar.gz | |
cleanup templating code
Signed-off-by: Robert Günzler <r@gnzler.io>
| -rw-r--r-- | src/main.zig | 70 |
1 files changed, 37 insertions, 33 deletions
diff --git a/src/main.zig b/src/main.zig index 3e2fa7e..1a4a86c 100644 --- a/src/main.zig +++ b/src/main.zig @@ -16,8 +16,6 @@ const LICENSE_NAME = "BY-NC-SA 4.0"; const LICENSE_URL = "https://git.sr.ht/~robertgzr/site/blob/rabbits/LICENSE.content"; const SOURCE_URL = "https://git.sr.ht/~robertgzr/site/tree/rabbits"; -const BuildErrors = (std.fs.File.OpenError || std.fs.File.WriteError || std.mem.Allocator.Error); - // tune std.log options pub const std_options = .{ .log_level = .info, @@ -56,7 +54,7 @@ fn joinIn(allocator: std.mem.Allocator, paths: []const []const u8, filename_part return try std.fs.path.join(allocator, paths2); } -fn portal(allocator: std.mem.Allocator, f: std.fs.File, refname: []const u8, insert_heading: bool) BuildErrors!void { +fn portal(allocator: std.mem.Allocator, w: std.io.AnyWriter, refname: []const u8, insert_heading: bool) anyerror!void { const basename = try std.mem.replaceOwned(u8, allocator, refname, " ", "_"); defer allocator.free(basename); const refpathPage = try joinIn(allocator, &.{PAGE_PATH}, &.{ basename, ".htm" }); @@ -65,7 +63,7 @@ fn portal(allocator: std.mem.Allocator, f: std.fs.File, refname: []const u8, ins defer allocator.free(refpathSite); if (insert_heading) - try f.writer().print( + try w.print( \\<h2 id="{[ID]s}"><a href="/{[PATH]s}">{[NAME]s}</a></2> \\ , .{ @@ -74,21 +72,18 @@ fn portal(allocator: std.mem.Allocator, f: std.fs.File, refname: []const u8, ins .PATH = refpathSite, }); - try inject(allocator, f, refpathPage); + try inject(allocator, w, refpathPage); // XXX: track ref count? } -fn template(allocator: std.mem.Allocator, f: std.fs.File, refname: []const u8) BuildErrors!void { - if (std.mem.startsWith(u8, refname, "/")) - return try portal(allocator, f, refname[1..], false); - +fn ref(allocator: std.mem.Allocator, w: std.io.AnyWriter, refname: []const u8) anyerror!void { const basename = try std.mem.replaceOwned(u8, allocator, refname, " ", "_"); defer allocator.free(basename); const refpathSite = try joinIn(allocator, &.{SITE_PATH}, &.{ basename, ".html" }); defer allocator.free(refpathSite); - try f.writer().print( + try w.print( \\<a href="/{[PATH]s}">{[NAME]s}</a> \\ , .{ @@ -99,7 +94,16 @@ fn template(allocator: std.mem.Allocator, f: std.fs.File, refname: []const u8) B // XXX: track ref count? } -fn inject(allocator: std.mem.Allocator, f: std.fs.File, srcpath: []const u8) BuildErrors!void { +fn template(allocator: std.mem.Allocator, w: std.io.AnyWriter, refname: []const u8) anyerror!void { + if (std.mem.startsWith(u8, refname, "/")) { + return try portal(allocator, w, refname[1..], false); + } else { + return try ref(allocator, w, refname); + } +} + +// Parses srcpath, resolves refs and portals and writes everything to w +fn inject(allocator: std.mem.Allocator, w: std.io.AnyWriter, srcpath: []const u8) !void { const inc = std.fs.cwd().openFile(srcpath, .{ .mode = .read_only }) catch |err| { if (err == error.FileNotFound) std.log.warn("Missing {s} include.", .{srcpath}); @@ -108,7 +112,7 @@ fn inject(allocator: std.mem.Allocator, f: std.fs.File, srcpath: []const u8) Bui }; defer inc.close(); - var buf_writer = std.io.bufferedWriter(f.writer()); + var buf_writer = std.io.bufferedWriter(w); var out_stream = buf_writer.writer(); var buf_reader = std.io.bufferedReader(inc.reader()); @@ -116,37 +120,36 @@ fn inject(allocator: std.mem.Allocator, f: std.fs.File, srcpath: []const u8) Bui var arena = std.heap.ArenaAllocator.init(allocator); defer arena.deinit(); + while (in_stream.readUntilDelimiterOrEofAlloc( arena.allocator(), '\n', buf_reader.buf.len, - ) catch @panic("Failed to read from stream")) |chunk| { - if (std.mem.indexOfPosLinear(u8, chunk, 0, "{")) |start| { - try out_stream.writeAll(chunk[0..start]); - try buf_writer.flush(); + ) catch { + @panic("Failed to read from stream"); + }) |chunk| { + defer _ = arena.reset(.free_all); + if (std.mem.indexOfPosLinear(u8, chunk, 0, "{")) |start| { if (std.mem.indexOfPosLinear(u8, chunk, start + 1, "}")) |end| { - try template(allocator, f, chunk[start + 1 .. end]); - try buf_writer.flush(); - + try out_stream.writeAll(chunk[0..start]); + template(allocator, out_stream.any(), chunk[start + 1 .. end]) catch + @panic("Failed to resolve template"); try out_stream.writeAll(chunk[end + 1 ..]); - try buf_writer.flush(); - } else { - // NOTE: we need to print the opening brace. we did not find a - // closing brace on the same line, so this isn't a ref - try out_stream.writeAll("{"); + try out_stream.writeByte('\n'); + continue; } - } else { - try out_stream.writeAll(chunk); - try out_stream.writeByte('\n'); } - _ = arena.reset(.free_all); + + try out_stream.writeAll(chunk); + try out_stream.writeByte('\n'); + try buf_writer.flush(); } try buf_writer.flush(); } -fn build(allocator: std.mem.Allocator, f: std.fs.File, page_name: []const u8, srcpath: []const u8) BuildErrors!void { +fn build(allocator: std.mem.Allocator, f: std.fs.File, page_name: []const u8, srcpath: []const u8) !void { const mtime = blk: { const attr = try allocator.create(std.os.linux.Stat); defer allocator.destroy(attr); @@ -193,7 +196,7 @@ fn build(allocator: std.mem.Allocator, f: std.fs.File, page_name: []const u8, sr \\<nav> \\ ); - portal(allocator, f, "meta.nav", false) catch {}; // ignore error + portal(allocator, f.writer().any(), "meta.nav", false) catch {}; // ignore error try f.writer().writeAll( \\</nav> \\ @@ -210,7 +213,7 @@ fn build(allocator: std.mem.Allocator, f: std.fs.File, page_name: []const u8, sr , .{ .PAGE_NAME = page_name, }); - try inject(allocator, f, srcpath); + try inject(allocator, f.writer().any(), srcpath); try f.writer().writeAll( \\ \\</main> @@ -432,14 +435,15 @@ pub fn main() !void { std.log.info("Indexed {d} pages.", .{pages.len}); - std.log.info("Generated index.", .{}); - var ctx = Context{ .allocator = allocator, .pages = pages, }; try genIndexHtml(&ctx); + + std.log.info("Generated index.", .{}); + try genSite(&ctx); std.log.info("Generated {d} files.", .{ctx.generated}); |