Makko, the people-oriented static site generator made for blogging.
forge.starlightnet.work/Team/Makko
ssg
static-site-generator
makko
starlight-network
1const std = @import("std");
2
3const Makko = @import("Makko.zig");
4const Data = @import("Data.zig");
5const helper = @import("helper.zig");
6const network = @import("network.zig");
7const MakkoWatcher = zm.Watcher(*Makko);
8
9const zm = @import("zigmon");
10
11var mutex: std.Thread.Mutex = .{};
12var server: *network.Server = undefined;
13
14fn onTemplateChange(
15 watcher: MakkoWatcher,
16 _: zm.Action,
17 path: []const u8,
18 _: ?[]const u8,
19) void {
20 const makko = watcher.data;
21 const log = makko.log;
22
23 if (std.mem.containsAtLeast(u8, path, 1, ".."))
24 return;
25
26 if (std.mem.containsAtLeast(u8, path, 1, std.fs.path.sep_str))
27 return; // it's a folder or within a folder, we don't care about this file.
28
29 if (helper.isDir(makko.paths.template, path))
30 return;
31
32 mutex.lock();
33 defer mutex.unlock();
34
35 makko.loadTemplates() catch |err|
36 log.warn("Could not reload templates! ({})", .{err});
37
38 const basename = std.fs.path.basename(path);
39 if (std.mem.eql(u8, basename, "feed.html"))
40 makko.generateFeeds() catch |err|
41 log.warn("Could not generate feeds! ({})", .{err});
42
43 if (std.mem.eql(u8, basename, "post.html")) {
44 var pass = makko.automaticPass() catch |err|
45 log.fatal("Could not regenerate! ({})", .{err});
46 defer pass.deinit();
47
48 pass.runCallbacks() catch |err|
49 log.warn("Could not run callbacks! ({})", .{err});
50 }
51
52 makko.storeDatabase() catch |err|
53 log.fatal("Could not store database!!! ({})", .{err});
54
55 server.handler.update();
56}
57
58fn onPostChange(
59 watcher: MakkoWatcher,
60 action: zm.Action,
61 path: []const u8,
62 _: ?[]const u8,
63) void {
64 const makko = watcher.data;
65 const log = makko.log;
66
67 if (std.mem.containsAtLeast(u8, path, 1, ".."))
68 return;
69
70 mutex.lock();
71 defer mutex.unlock();
72
73 var pass = makko.newPass();
74 defer pass.deinit();
75
76 if (action == .delete) {
77 pass.deleteFileByPath(path) catch |err|
78 log.fatal("Could not delete file! ({})", .{err});
79
80 makko.generateFeeds() catch |err|
81 log.warn("Could not generate feeds! ({})", .{err});
82
83 return;
84 }
85
86 if (helper.isDir(makko.paths.source, path)) {
87 makko.paths.output.makeDir(path) catch {};
88 return;
89 }
90
91 const maybe_visibility = pass.processFile(path) catch |err| blk: {
92 log.err("Could not process file! ({})", .{err});
93 break :blk .secret;
94 };
95
96 if (maybe_visibility) |visibility|
97 if (visibility == .public)
98 makko.generateFeeds() catch |err|
99 log.warn("Could not generate feeds! ({})", .{err});
100
101 pass.runCallbacks() catch |err|
102 log.warn("Could not run callbacks! ({})", .{err});
103
104 makko.storeDatabase() catch |err|
105 log.fatal("Could not store database!!! ({})", .{err});
106
107 server.handler.update();
108}
109
110pub fn live(public: bool, port: u16, makko: *Makko) !void {
111 makko.progress.end();
112 makko.progress = .{ .index = .none };
113
114 try makko.paths.root.setAsCwd();
115
116 zm.init();
117 defer zm.deinit();
118
119 const template_path_z = try makko.allocator.dupeZ(
120 u8,
121 makko.origin.value.paths.templates,
122 );
123 defer makko.allocator.free(template_path_z);
124 var template_watcher: MakkoWatcher = .{
125 .data = makko,
126 .root = template_path_z,
127 .on_change = onTemplateChange,
128 };
129 try template_watcher.watch();
130 defer template_watcher.unwatch();
131
132 const source_path_z = try makko.allocator.dupeZ(
133 u8,
134 makko.origin.value.paths.source,
135 );
136 defer makko.allocator.free(source_path_z);
137 var blog_watcher: MakkoWatcher = .{
138 .data = makko,
139 .root = source_path_z,
140 .on_change = onPostChange,
141 };
142 try blog_watcher.watch();
143 defer blog_watcher.unwatch();
144
145 var srv = try network.init(makko, public, port);
146 server = &srv;
147 _ = try srv.listen();
148 defer srv.deinit();
149 defer srv.stop();
150
151 _ = try std.io.getStdOut().write("\n");
152}