Initial commit
This commit is contained in:
commit
bda33ef628
36 changed files with 4233 additions and 0 deletions
54
src/frontmatter.zig
Normal file
54
src/frontmatter.zig
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
const std = @import("std");
|
||||
|
||||
pub const FrontMatter = struct {
|
||||
meta: std.StringHashMap([]const u8),
|
||||
content: []const u8,
|
||||
|
||||
pub fn deinit(self: *FrontMatter) void {
|
||||
self.meta.deinit();
|
||||
}
|
||||
|
||||
pub fn get(self: *const FrontMatter, key: []const u8) ?[]const u8 {
|
||||
return self.meta.get(key);
|
||||
}
|
||||
};
|
||||
|
||||
pub fn parse(allocator: std.mem.Allocator, input: []const u8) !FrontMatter {
|
||||
var meta = std.StringHashMap([]const u8).init(allocator);
|
||||
errdefer meta.deinit();
|
||||
|
||||
if (!std.mem.startsWith(u8, input, "---")) {
|
||||
return FrontMatter{ .meta = meta, .content = input };
|
||||
}
|
||||
|
||||
const after_open = input[3..];
|
||||
const close_idx = std.mem.indexOf(u8, after_open, "\n---");
|
||||
if (close_idx == null) {
|
||||
return FrontMatter{ .meta = meta, .content = input };
|
||||
}
|
||||
|
||||
const front_matter_block = after_open[0..close_idx.?];
|
||||
const content_start = 3 + close_idx.? + 4;
|
||||
const content = if (content_start < input.len) skipLeadingNewlines(input[content_start..]) else "";
|
||||
|
||||
var lines = std.mem.splitScalar(u8, front_matter_block, '\n');
|
||||
while (lines.next()) |line| {
|
||||
const trimmed = std.mem.trim(u8, line, " \t\r");
|
||||
if (trimmed.len == 0) continue;
|
||||
|
||||
if (std.mem.indexOf(u8, trimmed, ":")) |colon_idx| {
|
||||
const key = std.mem.trim(u8, trimmed[0..colon_idx], " \t");
|
||||
const value = std.mem.trim(u8, trimmed[colon_idx + 1 ..], " \t");
|
||||
if (std.mem.eql(u8, key, "content") or std.mem.eql(u8, key, "nav_html") or std.mem.eql(u8, key, "toc")) return error.ReservedFrontmatterKey;
|
||||
try meta.put(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
return FrontMatter{ .meta = meta, .content = content };
|
||||
}
|
||||
|
||||
fn skipLeadingNewlines(s: []const u8) []const u8 {
|
||||
var i: usize = 0;
|
||||
while (i < s.len and (s[i] == '\n' or s[i] == '\r')) : (i += 1) {}
|
||||
return s[i..];
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue