about summary refs log tree commit diff
path: root/src/Context.zig
diff options
context:
space:
mode:
authorRobert Günzler <r@gnzler.io>2026-09-18 04:00:18 +0200
committerRobert Günzler <r@gnzler.io>2026-09-22 22:37:51 +0200
commit5bc242742e1225c7c3b87a31c2c2a3998ac18685 (patch)
treebaae923037b49ba31bb0a15ece2eec4bea13ab25 /src/Context.zig
parentc677e8873e0eae790a1b8b07844a10efa9f63a1e (diff)
downloadsite-5bc242742e1225c7c3b87a31c2c2a3998ac18685.tar.gz
v2
Signed-off-by: Robert Günzler <r@gnzler.io>
Diffstat (limited to '')
-rw-r--r--src/Context.zig242
1 files changed, 0 insertions, 242 deletions
diff --git a/src/Context.zig b/src/Context.zig
deleted file mode 100644
index f5a638e..0000000
--- a/src/Context.zig
+++ /dev/null
@@ -1,242 +0,0 @@
-const std = @import("std");
-
-const Content = @import("Content.zig");
-const FileSwapper = @import("FileSwapper.zig");
-const gen = @import("gen.zig");
-
-const Context = @This();
-const log = std.log.scoped(.Context);
-
-pub const Defaults = struct {
-    // TODO: should this be next to the root_path of Context.index?
-    pub const CONTENT_PATH = ".rbc/content";
-    pub const CONTENT_REF = "../..";
-
-    pub const SITE_NAME = "gzr.im";
-    pub const LICENSE_HOLDER = "robertgzr";
-    pub const LICENSE_YEAR = "2025";
-    pub const LICENSE_NAME = "BY-NC-SA 4.0";
-    pub const LICENSE_URL = "https://git.sr.ht/~robertgzr/site/blob/master/LICENSE.content";
-    pub const SOURCE_URL = "https://git.sr.ht/~robertgzr/site/tree/master";
-    pub const PUBLIC_INBOX = "~robertgzr/public-inbox@lists.sr.ht";
-};
-
-io: std.Io,
-arena: std.heap.ArenaAllocator,
-content: ?Content = null,
-root: ?std.Io.Dir = null,
-
-pub fn init(io: std.Io, gpa: std.mem.Allocator) !Context {
-    return .{
-        .io = io,
-        .arena = std.heap.ArenaAllocator.init(gpa),
-    };
-}
-
-pub fn deinit(self: *Context) void {
-    if (self.content != null) {
-        self.content.?.deinit();
-    }
-    self.arena.deinit();
-}
-
-pub fn index(self: *Context, root_dir: std.Io.Dir) !void {
-    if (self.content == null) {
-        // setup content store
-        const content_dir = try root_dir.createDirPathOpen(
-            self.io,
-            Defaults.CONTENT_PATH,
-            .{ .open_options = .{ .iterate = true } },
-        );
-        self.content = try Content.init(self.io, self.arena.allocator(), content_dir);
-        self.root = root_dir;
-    } else {
-        try self.gc();
-    }
-
-    var walk = try root_dir.walkSelectively(self.arena.allocator());
-    defer walk.deinit();
-
-    var digests: std.ArrayList(Content.Digest) = .empty;
-    defer digests.deinit(self.arena.allocator());
-
-    while (try walk.next(self.io)) |e| {
-        switch (e.kind) {
-            .file => {
-                if (std.mem.endsWith(u8, e.basename, ".htm")) {
-                    const dgst = try self.content.?.add(root_dir, e.path);
-                    try self.content.?.propSet(dgst, "link", e.path);
-
-                    try digests.append(self.arena.allocator(), dgst);
-                    log.debug("Indexing page {s} (digest={s})", .{ e.path, dgst });
-                }
-            },
-            else => {},
-        }
-    }
-
-    log.info("Indexed {d} pages", .{digests.items.len});
-}
-
-// garbage collect
-fn gc(self: *Context) !void {
-    if (self.content == null) {
-        return error.NoIndex;
-    }
-
-    var etor = try self.content.?.enumerate(self.arena.allocator());
-    defer etor.deinit();
-
-    var gc_n: usize = 0;
-    while (try etor.next()) |dgst| {
-        if (try self.content.?.propGet(dgst, "link", self.arena.allocator())) |link| {
-            defer self.arena.allocator().free(link);
-
-            // cleanup entries with missing link
-            self.root.?.access(self.io, link, .{}) catch |err| switch (err) {
-                error.FileNotFound => {
-                    try self.content.?.del(dgst);
-                    gc_n += 1;
-                },
-                else => return err,
-            };
-        }
-    }
-
-    log.info("Garbage collected {d} pages", .{gc_n});
-}
-
-pub fn render(self: *Context, site_dir: std.Io.Dir, force: bool) !void {
-    if (self.content == null) {
-        return error.NoIndex;
-    }
-
-    log.info("Rendering site", .{});
-
-    var page_n: u32 = 0;
-
-    var etor = try self.content.?.enumerate(self.arena.allocator());
-    defer etor.deinit();
-
-    // render pages
-    while (try etor.next()) |dgst| {
-        if (!force and try self.hasRenderPage(dgst, site_dir)) {
-            continue; // no need to re-render
-        }
-
-        try self.renderPage(site_dir, dgst);
-        page_n += 1;
-    }
-
-    log.info("Rendered {d} pages", .{page_n});
-}
-
-fn hasRenderPage(self: *Context, dgst: Content.Digest, site_dir: std.Io.Dir) !bool {
-    const render_path = try self.content.?.propGet(dgst, "render", self.arena.allocator());
-    if (render_path == null) {
-        return false;
-    }
-    defer self.arena.allocator().free(render_path.?);
-
-    site_dir.access(self.io, render_path.?, .{}) catch |err| switch (err) {
-        error.FileNotFound => return false,
-        else => return err,
-    };
-
-    log.debug("Skipping {s}", .{render_path.?});
-    return true;
-}
-
-fn renderPage(self: *Context, site_dir: std.Io.Dir, dgst: Content.Digest) !void {
-    var arena = std.heap.ArenaAllocator.init(self.arena.allocator());
-    defer arena.deinit();
-    const gpa = arena.allocator();
-
-    const page_path = try self.content.?.propGet(dgst, "link", self.arena.allocator());
-    if (page_path == null) {
-        return error.NoLink;
-    }
-
-    const page_name = std.mem.cutSuffix(u8, std.fs.path.basename(page_path.?), ".htm").?;
-
-    if (std.mem.startsWith(u8, page_name, "meta.")) {
-        log.warn("skipping meta page => {s}", .{page_name});
-        return;
-    } else {
-        log.debug("Rendering page {s} (name={s})", .{ page_path.?, page_name });
-
-        const render_name = try std.mem.concat(gpa, u8, &.{ page_name, ".html" });
-        const pretty_name = try std.mem.replaceOwned(u8, gpa, page_name, "_", " ");
-
-        const sw = try FileSwapper.createAt(self.io, gpa, site_dir, render_name);
-        defer sw.close();
-        var w = sw.writer();
-
-        try gen.build_htm(self.io, gpa, &w.interface, .{
-            .root_dir = self.root.?,
-            .site_dir = site_dir,
-            .page_path = page_path.?,
-            .page_name = pretty_name,
-            .meta = .{
-                .site_name = Defaults.SITE_NAME,
-                .license_url = Defaults.LICENSE_URL,
-                .license_holder = Defaults.LICENSE_HOLDER,
-                .license_year = Defaults.LICENSE_YEAR,
-                .license_name = Defaults.LICENSE_NAME,
-                .public_inbox = Defaults.PUBLIC_INBOX,
-                .source_url = Defaults.SOURCE_URL,
-            },
-        });
-
-        try self.content.?.propSet(dgst, "render", render_name);
-        try self.content.?.propSet(dgst, "name", pretty_name);
-    }
-}
-
-// test "e2e" {
-//     std.testing.log_level = .debug;
-//
-//     const DEMO_DIR: []const u8 = "/home/robert/tmp/rbc-demo/";
-//     const SITE_DIR: []const u8 = DEMO_DIR ++ "site/";
-//
-//     const demo_dir = try std.Io.Dir.cwd().openDir(std.testing.io, DEMO_DIR, .{ .iterate = true });
-//     defer demo_dir.close(std.testing.io);
-//     const site_dir = try std.Io.Dir.cwd().createDirPathOpen(std.testing.io, SITE_DIR, .{});
-//     defer site_dir.close(std.testing.io);
-//
-//     var ctx = try Context.init(std.testing.io, std.testing.allocator);
-//     defer ctx.deinit();
-//
-//     try ctx.index(demo_dir);
-//     try ctx.render(site_dir);
-//
-//     // TODO:
-//     // index; build a list of input files
-//     // parse; detect backlinks, dependencies, etc.
-//     // render; write output
-// }
-
-test "gc" {
-    std.testing.log_level = .debug;
-
-    var tmp = std.testing.tmpDir(.{ .iterate = true });
-    defer tmp.cleanup();
-
-    const tmp_src = try tmp.dir.createDirPathOpen(std.testing.io, "src", .{ .open_options = .{ .iterate = true } });
-    // const tmp_dst = try tmp.dir.createDirPathOpen(std.testing.io, "dst", .{});
-
-    try tmp_src.writeFile(std.testing.io, .{ .sub_path = "foo.htm", .data = "hello world" });
-
-    var ctx = try Context.init(std.testing.io, std.testing.allocator);
-    defer ctx.deinit();
-
-    try ctx.index(tmp_src);
-    try tmp_src.deleteFile(std.testing.io, "foo.htm");
-
-    try ctx.index(tmp_src);
-    var etor = try ctx.content.?.enumerate(std.testing.allocator);
-    defer etor.deinit();
-    var seen: u32 = 0;
-    while (try etor.next()) |_| seen += 1;
-    try std.testing.expect(seen == 0);
-}