about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/gen.zig91
1 files changed, 62 insertions, 29 deletions
diff --git a/src/gen.zig b/src/gen.zig
index 6c7abcf..79a3ea8 100644
--- a/src/gen.zig
+++ b/src/gen.zig
@@ -286,8 +286,15 @@ fn inject(allocator: std.mem.Allocator, w: std.io.AnyWriter, srcpath: []const u8
             if (std.mem.indexOfPosLinear(u8, chunk, 0, "{")) |start| {
                 if (std.mem.indexOfPosLinear(u8, chunk, start + 1, "}")) |end| {
                     try out_stream.writeAll(chunk[0..start]);
-                    template(allocator, out_stream.any(), chunk[start + 1 .. end]) catch
-                        @panic("Failed to resolve template");
+                    template(allocator, out_stream.any(), chunk[start + 1 .. end]) catch |err| switch (err) {
+                        error.FileNotFound => {
+                            // log.warn("ref {s} not found", .{chunk[start + 1 .. end]});
+                            // trim already written chunk and exit templating
+                            chunk = chunk[start..];
+                            break :templating;
+                        },
+                        else => @panic("Failed to resolve template"),
+                    };
                     chunk = chunk[end + 1 ..];
                 } else break :templating;
             } else break :templating;
@@ -311,57 +318,83 @@ fn template(allocator: std.mem.Allocator, w: std.io.AnyWriter, refname: []const
     }
 }
 
+const Page = struct {
+    arena: std.heap.ArenaAllocator,
+    ref: []const u8,
+    name: []const u8,
+    html: []const u8,
+    htm: []const u8,
+    anchor: []const u8,
+
+    fn from_ref(allocator: std.mem.Allocator, refname: []const u8) !Page {
+        var arena = std.heap.ArenaAllocator.init(allocator);
+
+        const endofref = std.mem.lastIndexOf(u8, refname, "#") orelse refname.len;
+        const basename = try std.mem.replaceOwned(u8, arena.allocator(), refname[0..endofref], " ", "_");
+        const html = try fs.join_path_and_filename(arena.allocator(), &.{Context.params.SITE_PATH}, &.{ basename, ".html" });
+        const htm = try fs.join_path_and_filename(arena.allocator(), &.{Context.params.PAGE_PATH}, &.{ basename, ".htm" });
+
+        try std.fs.cwd().access(htm, .{ .mode = .read_only });
+
+        return .{
+            .arena = arena,
+            .ref = refname[0..endofref],
+            .name = basename,
+            .html = html,
+            .htm = htm,
+            .anchor = if (endofref < refname.len) refname[endofref..] else "",
+        };
+    }
+
+    fn deinit(self: Page) void {
+        self.arena.deinit();
+    }
+};
+
 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 fs.join_path_and_filename(allocator, &.{Context.params.PAGE_PATH}, &.{ basename, ".htm" });
-    defer allocator.free(refpathPage);
-    const refpathSite = try fs.join_path_and_filename(allocator, &.{Context.params.SITE_PATH}, &.{ basename, ".html" });
-    defer allocator.free(refpathSite);
+    const page = try Page.from_ref(allocator, refname);
+    defer page.deinit();
 
     if (insert_heading)
         try w.print(
             \\<h2 id="{[ID]s}"><a href="/{[PATH]s}">{[NAME]s}</a></2>
             \\
         , .{
-            .ID = basename,
-            .NAME = refname,
-            .PATH = refpathSite,
+            .ID = page.ref,
+            .NAME = page.name,
+            .PATH = page.html,
         });
 
-    try inject(allocator, w, refpathPage);
+    try inject(allocator, w, page.htm);
 
     // XXX: track ref count?
 }
 
 fn ref(allocator: std.mem.Allocator, w: std.io.AnyWriter, refname: []const u8) anyerror!void {
-    const endofref = std.mem.lastIndexOf(u8, refname, "#") orelse refname.len;
-
-    const basename = try std.mem.replaceOwned(u8, allocator, refname[0..endofref], " ", "_");
-    defer allocator.free(basename);
-    const refpathSite = try fs.join_path_and_filename(allocator, &.{Context.params.SITE_PATH}, &.{ basename, ".html" });
-    defer allocator.free(refpathSite);
+    const page = try Page.from_ref(allocator, refname);
+    defer page.deinit();
 
     try w.print(
-        \\<a href="/{[PATH]s}{[anchor]s}">{[NAME]s}</a>
+        \\<a href="/{[PATH]s}{[ANCHOR]s}">{[NAME]s}</a>
     , .{
-        .NAME = refname[0..endofref],
-        .PATH = refpathSite,
-        .anchor = if (endofref < refname.len) refname[endofref..] else "",
+        .NAME = page.name,
+        .PATH = page.html,
+        .ANCHOR = page.anchor,
     });
 
     // XXX: track ref count?
 }
 
 fn ref_link(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 fs.join_path_and_filename(allocator, &.{Context.params.SITE_PATH}, &.{ basename, ".html" });
-    defer allocator.free(refpathSite);
+    const page = try Page.from_ref(allocator, refname);
+    defer page.deinit();
 
-    try w.print("/{s}", .{refpathSite});
+    try w.print("/{s}", .{page.html});
 }
 
-fn ref_name(_: std.mem.Allocator, w: std.io.AnyWriter, refname: []const u8) anyerror!void {
-    try w.print("{s}", .{refname});
+fn ref_name(allocator: std.mem.Allocator, w: std.io.AnyWriter, refname: []const u8) anyerror!void {
+    const page = try Page.from_ref(allocator, refname);
+    defer page.deinit();
+
+    try w.print("{s}", .{page.ref});
 }