size: 1 KiB

1const std = @import("std");
2const mem = std.mem;
3const fs = std.fs;
4const println = @import("utils.zig").println;
5const Djot = @import("Djot.zig");
6
7pub const Post = @This();
8
9slug: []const u8,
10title: []const u8 = "",
11published_at: []const u8 = "",
12djot_text: []const u8 = "",
13
14pub fn init(gpa: mem.Allocator, input: []const u8, file_path: []const u8) !Post {
15 const fence = "```";
16 var post = Post{
17 .slug = try gpa.dupe(u8, fs.path.dirname(file_path).?),
18 };
19
20 var lines = mem.splitScalar(u8, input, '\n');
21 var idx: usize = 0;
22
23 const first_line = lines.next().?;
24 if (!mem.eql(u8, first_line, fence)) {
25 @panic("First line must be " ++ fence ++ " to start frontmatter");
26 }
27 idx += first_line.len + 1;
28
29 // Read frontmatter line by line
30 while (lines.next()) |line| {
31 defer idx += line.len + 1;
32
33 if (mem.eql(u8, line, fence)) {
34 break;
35 }
36 if (mem.startsWith(u8, line, "title: ")) {
37 post.title = try gpa.dupe(u8, line["title: ".len..]);
38 } else if (mem.startsWith(u8, line, "published_at: ")) {
39 post.published_at = try gpa.dupe(u8, line["published_at: ".len..]);
40 }
41 }
42
43 post.djot_text = try gpa.dupe(u8, mem.trimLeft(u8, input[idx..], "\n\t "));
44 return post;
45}
46
47pub fn deinit(self: Post, gpa: mem.Allocator) void {
48 gpa.free(self.slug);
49 gpa.free(self.title);
50 gpa.free(self.published_at);
51 gpa.free(self.djot_text);
52}
53
54pub fn newestFirst(_: void, lhs: Post, rhs: Post) bool {
55 return mem.lessThan(u8, rhs.published_at, lhs.published_at);
56}