diff options
| author | Robert Günzler <r@gnzler.io> | 2026-09-24 16:45:51 +0200 |
|---|---|---|
| committer | Robert Günzler <r@gnzler.io> | 2026-10-02 10:39:48 +0200 |
| commit | 8b578bb5e442359167efda57798693cac7793f61 (patch) | |
| tree | e92138e3a73957cce1a6521a90e8e5bbce84c48f /src | |
| parent | 6ed8796d936d231179ca6fb7a419f6c4f005c03e (diff) | |
| download | site-8b578bb5e442359167efda57798693cac7793f61.tar.gz | |
refactor backrefs generation
Signed-off-by: Robert Günzler <r@gnzler.io>
Diffstat (limited to '')
| -rw-r--r-- | src/inc/meta.baseof.htm | 2 | ||||
| -rw-r--r-- | src/main.zig | 87 |
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), |