diff options
| author | Robert Günzler <r@gnzler.io> | 2026-09-24 16:46:29 +0200 |
|---|---|---|
| committer | Robert Günzler <r@gnzler.io> | 2026-10-02 10:39:48 +0200 |
| commit | 1821d750aa0be2f8662001fc90e888a4c2bb9a3f (patch) | |
| tree | c109343919a23e7fe08818f88d02ef397987589b /src | |
| parent | 8b578bb5e442359167efda57798693cac7793f61 (diff) | |
| download | site-1821d750aa0be2f8662001fc90e888a4c2bb9a3f.tar.gz | |
support generating index
Signed-off-by: Robert Günzler <r@gnzler.io>
Diffstat (limited to 'src')
| -rw-r--r-- | src/main.zig | 76 |
1 files changed, 63 insertions, 13 deletions
diff --git a/src/main.zig b/src/main.zig index 6804735..a8603c7 100644 --- a/src/main.zig +++ b/src/main.zig @@ -270,6 +270,11 @@ const Cli = struct { } { + var pn = if (!DEBUG) progress.start("Generating index", 0); + defer if (!DEBUG) pn.end(); + try genIndex(io, gpa, root_dir, target_dir, index); + } + { 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); @@ -359,6 +364,28 @@ const Cli = struct { } } + fn genIndex( + io: Io, + gpa: Allocator, + root_dir: Io.Dir, + target_dir: Io.Dir, + index: std.ArrayList([]const u8), + ) !void { + log.info("Generating index", .{}); + + var source = File.init(io, root_dir, "index.htm", null) catch |err| + switch (err) { + error.FileNotFound => return, + else => return err, + }; + defer source.close(io); + + const b = try Builder.init(gpa, root_dir, source, target_dir); + b.index = index; + defer b.deinit(gpa); + try b.build(io, gpa); + } + fn serve(io: Io, _: Allocator, _: FlagSet, args: [][]const u8) !void { if (args.len != 1) return Cli.usage(); @@ -429,10 +456,13 @@ const Builder = struct { dgsts: std.ArrayList(Digest) = .empty, // track references refs: std.ArrayList([]const u8) = .empty, + // used for post processing + index: ?std.ArrayList([]const u8) = null, pub const Options = struct { - // TODO: this is a bit of a hack no? - offset_from_siteroot: ?[]const u8, + // TODO: this is a bit of a hack no? we should just track the target + // path and use that + offset_from_siteroot: ?[]const u8 = "/site", }; const DELIM_START: []const u8 = "{["; @@ -444,9 +474,7 @@ const Builder = struct { .root_dir = root_dir, .source = source, .target_dir = target_dir, - .options = .{ - .offset_from_siteroot = "/site", - }, + .options = .{}, }; return b; } @@ -588,6 +616,32 @@ const Builder = struct { try w.writeAll("{[builtin.backrefs]}"); // done in post processing return; } + if (std.mem.eql(u8, ref_name, "builtin.index")) { + if (self.index == null) { + try w.writeAll("{[builtin.backrefs]}"); // done in post processing + return; + } + + std.debug.assert(self.index != null); + try w.writeAll( + \\<nav> + \\<ul> + \\ + ); + for (self.index.?.items) |e| try w.print( + \\<li><a href="{s}">{s}</a></li> + \\ + , .{ + try formatLink(gpa, std.fs.path.stem(e), self.options.offset_from_siteroot), + try formatName(gpa, std.fs.path.stem(e)), + }); + try w.writeAll( + \\</ul> + \\</nav> + \\ + ); + return; + } switch (ref_name[0]) { '/' => try self.templatePortal(io, gpa, ref_name[1..], w), @@ -772,14 +826,10 @@ fn formatName(gpa: Allocator, name: []const u8) ![]u8 { return try std.mem.replaceOwned(u8, gpa, name, "_", " "); } -fn formatLink(gpa: Allocator, name: []const u8, offset: ?[]const u8) ![]u8 { - var link = try std.fmt.allocPrint(gpa, "{s}.html", .{name}); - if (offset) |_| { - const link2 = try std.fs.path.join(gpa, &.{ offset.?, link }); - gpa.free(link); - link = link2; - } - return link; +fn formatLink(gpa: Allocator, name: []const u8, pathPrefix: ?[]const u8) ![]u8 { + const link_name = try std.fmt.allocPrint(gpa, "{s}.html", .{name}); + defer gpa.free(link_name); + return try std.fs.path.join(gpa, &.{ pathPrefix orelse "/", link_name }); } fn targetExists(io: Io, gpa: Allocator, target_dir: Io.Dir, sub_path: []const u8, root_dir: Io.Dir) !bool { |