Makko, the people-oriented static site generator made for blogging. forge.starlightnet.work/Team/Makko
ssg static-site-generator makko starlight-network
at main 4.1 kB view raw
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}