about summary refs log tree commit diff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/inc/meta.baseof.htm2
-rw-r--r--src/main.zig87
2 files changed, 62 insertions, 27 deletions
diff --git a/src/inc/meta.baseof.htm b/src/inc/meta.baseof.htm
index 8172a75..13075c3 100644
--- a/src/inc/meta.baseof.htm
+++ b/src/inc/meta.baseof.htm
@@ -21,7 +21,7 @@
 		</header>
 		<main>
 			{[builtin.fragment]}
-			<section id="backrefs"><!-- no backrefs --></section>
+			<section id="backrefs">{[builtin.backrefs]}</section>
 		</main>
 		<footer>
 			Edited on {[builtin.mtime]} <a href="https://git.sr.ht/~robertgzr/site/tree/master/src/inc/{[builtin.path]}" target="_blank">[src]</a>
diff --git a/src/main.zig b/src/main.zig
index 27aa316..6804735 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -181,8 +181,6 @@ const Cli = struct {
         const target_dir = try Io.Dir.cwd().createDirPathOpen(io, target_path, .{});
         defer target_dir.close(io);
 
-        // TODO: parallelize?
-
         var work: std.ArrayList([]const u8) = .empty;
         defer work.deinit(gpa);
 
@@ -211,9 +209,10 @@ const Cli = struct {
         var htmProgress = if (!DEBUG) progress.start("Generating html", work.items.len);
         defer if (!DEBUG) htmProgress.end();
 
-        var outgoing: std.StringHashMapUnmanaged([][]const u8) = .empty;
-        defer outgoing.deinit(gpa);
+        var outgoingRefs: std.StringHashMapUnmanaged([][]const u8) = .empty;
+        defer outgoingRefs.deinit(gpa);
 
+        // TODO: parallelize?
         for (work.items) |path| {
             const md_name = try std.fmt.allocPrint(gpa, "{s}.md", .{std.fs.path.stem(path)});
             defer gpa.free(md_name);
@@ -260,18 +259,42 @@ const Cli = struct {
             const refs = try b.refs.clone(gpa);
             for (refs.items, 0..) |r, i| refs.items[i] = try gpa.dupe(u8, r);
             // track the refs for this source file
-            try outgoing.put(gpa, std.fs.path.stem(source.path), refs.items);
+            try outgoingRefs.put(gpa, std.fs.path.stem(source.path), refs.items);
+        }
+
+        // filter index for post processing
+        var index: std.ArrayList([]const u8) = try .initCapacity(gpa, work.items.len);
+        while (work.pop()) |e| {
+            if (std.mem.startsWith(u8, std.fs.path.stem(e), "meta.")) continue;
+            index.appendAssumeCapacity(e);
+        }
+
+        {
+            var pn = if (!DEBUG) progress.start("Generating backrefs", index.items.len);
+            defer if (!DEBUG) pn.end();
+            try genBackrefs(io, gpa, target_dir, target_path, index, outgoingRefs);
         }
+    }
+
+    fn genBackrefs(
+        io: Io,
+        gpa: Allocator,
+        target_dir: Io.Dir,
+        target_path: []const u8,
+        work: std.ArrayList([]const u8),
+        outgoingRefs: std.StringHashMapUnmanaged([][]const u8),
+    ) !void {
+        log.info("Generating backrefs", .{});
 
         // create incoming refs from outgoing refs
-        var incoming: std.StringHashMapUnmanaged([][]const u8) = .empty;
-        try incoming.ensureTotalCapacity(gpa, outgoing.size);
-        defer incoming.deinit(gpa);
+        var incomingRefs: std.StringHashMapUnmanaged([][]const u8) = .empty;
+        try incomingRefs.ensureTotalCapacity(gpa, outgoingRefs.size);
+        defer incomingRefs.deinit(gpa);
 
-        var outIter = outgoing.iterator();
+        var outIter = outgoingRefs.iterator();
         while (outIter.next()) |entry| {
             for (entry.value_ptr.*) |ref| {
-                const res = incoming.getOrPutAssumeCapacity(ref);
+                const res = incomingRefs.getOrPutAssumeCapacity(ref);
                 if (res.found_existing) {
                     res.value_ptr.* = try gpa.realloc(res.value_ptr.*, res.value_ptr.len + 1);
                     res.value_ptr.*[res.value_ptr.len - 1] = entry.key_ptr.*;
@@ -282,19 +305,19 @@ const Cli = struct {
             }
         }
 
-        var inIter = incoming.iterator();
-        while (inIter.next()) |entry| {
-            if (entry.value_ptr.len == 0) continue;
+        for (work.items) |path| {
+            const stem = std.fs.path.stem(path);
+            const back_refs = incomingRefs.get(stem);
 
-            const target_name = try std.fmt.allocPrint(gpa, "{s}.html", .{entry.key_ptr.*});
+            const target_name = try std.fmt.allocPrint(gpa, "{s}.html", .{stem});
             defer gpa.free(target_name);
 
-            log.info("{s}: backrefs n={d}", .{ target_name, entry.value_ptr.len });
+            log.debug("{s}: backrefs n={d}", .{ target_name, if (back_refs) |b| b.len else 0 });
 
             var target = try File.init(io, target_dir, target_name, null);
             defer target.close(io);
 
-            const BACKREFS = "<!-- no backrefs -->";
+            const BACKREFS = "{[builtin.backrefs]}";
             const offset = std.mem.indexOf(u8, target.mmap.memory, BACKREFS) orelse continue;
             const remainder = try gpa.dupe(u8, target.mmap.memory[offset + BACKREFS.len ..]);
             defer gpa.free(remainder);
@@ -303,21 +326,30 @@ const Cli = struct {
             const buf = blk: {
                 var buf = Io.Writer.Allocating.init(gpa);
                 defer buf.deinit();
-                try buf.writer.writeAll("<p>incoming:</p>");
-                try buf.writer.writeByte('\n');
-                try buf.writer.writeByte('\n');
-                try buf.writer.writeAll("<nav><ul>");
-                try buf.writer.writeByte('\n');
-                for (entry.value_ptr.*) |back_ref| {
+
+                // if the file doesnt have backrefs, we still have to write here
+                // so that the template string is resolved to empty
+                if (back_refs == null) break :blk "<!-- no backrefs -->";
+
+                try buf.writer.writeAll(
+                    \\<p>incoming:</p>
+                    \\<nav>
+                    \\<ul>
+                    \\
+                );
+                for (back_refs.?) |back_ref| {
                     const back_ref_name = try std.fmt.allocPrint(gpa, "{s}.html", .{back_ref});
                     const back_ref_path = try std.fs.path.join(gpa, &.{ "/", target_path, back_ref_name });
                     try buf.writer.print(
                         \\<li><a href="{s}">{s}</a></li>
+                        \\
                     , .{ back_ref_path, back_ref });
-                    try buf.writer.writeByte('\n');
                 }
-                try buf.writer.writeAll("</ul></nav>");
-                try buf.writer.writeByte('\n');
+                try buf.writer.writeAll(
+                    \\</ul>
+                    \\</nav>
+                    \\
+                );
                 break :blk try buf.toOwnedSlice();
             };
 
@@ -552,7 +584,10 @@ const Builder = struct {
             try w.writeAll(buf[0..n]);
             return;
         }
-        // TODO: other builtins?
+        if (std.mem.eql(u8, ref_name, "builtin.backrefs")) {
+            try w.writeAll("{[builtin.backrefs]}"); // done in post processing
+            return;
+        }
 
         switch (ref_name[0]) {
             '/' => try self.templatePortal(io, gpa, ref_name[1..], w),