about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main.zig29
-rw-r--r--src/preproc.lua60
2 files changed, 86 insertions, 3 deletions
diff --git a/src/main.zig b/src/main.zig
index 7b53295..c5956fc 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -785,6 +785,8 @@ const Builder = struct {
         log.debug("{s}: done", .{self.source.path});
     }
 
+    const prepocLua = @embedFile("preproc.lua");
+
     fn markdown(self: *Builder, io: Io, gpa: Allocator) !void {
         log.info("mdn : {s}", .{self.source.path});
 
@@ -800,12 +802,14 @@ const Builder = struct {
         });
         defer target_fd.close(io);
 
+        // embedded preproc.lua -> fd
+        // which we pass to the pandoc subshell
+        const fd = try memfd("preproc.lua", prepocLua);
         const pandoc_command = try std.fmt.allocPrint(gpa,
-            \\pandoc --from=markdown+wikilinks_title_after_pipe+autolink_bare_uris --to=html5 --lua-filter=../../preproc.lua --strip-comments --output={s} {s}
-        , .{ target_path, self.source.path });
+            \\pandoc --from=markdown+wikilinks_title_after_pipe+autolink_bare_uris --to=html5 --lua-filter=/dev/fd/{d} --strip-comments --output={s} {s}
+        , .{ fd, target_path, self.source.path });
         defer gpa.free(pandoc_command);
 
-        try self.root_dir.access(io, "../../preproc.lua", .{}); // check preproc script
         try shell(io, pandoc_command, .{ .cwd = .{ .dir = self.root_dir } });
 
         // track source
@@ -952,6 +956,25 @@ fn getXattrSourceComponents(gpa: Allocator, fd: Io.File) !?[][]const u8 {
 
 // shell
 
+pub fn memfd(name: [*:0]const u8, data: []const u8) !usize {
+    const fd = linux.memfd_create(name, 0);
+    if (linux.errno(fd) != .SUCCESS) return error.MemfdCreate;
+    const rc = linux.ftruncate(@intCast(fd), @intCast(data.len));
+    if (linux.errno(rc) != .SUCCESS) return error.Ftruncate;
+    const page = linux.mmap(
+        null,
+        data.len,
+        .{ .READ = true, .WRITE = true },
+        .{ .TYPE = .SHARED },
+        @intCast(fd),
+        0,
+    );
+    if (linux.errno(page) != .SUCCESS) return error.Mmap;
+    const ptr: [*]volatile u8 = @ptrFromInt(page);
+    @memcpy(ptr, data);
+    return fd;
+}
+
 pub fn shell(
     io: std.Io,
     command: []const u8,
diff --git a/src/preproc.lua b/src/preproc.lua
new file mode 100644
index 0000000..76f0678
--- /dev/null
+++ b/src/preproc.lua
@@ -0,0 +1,60 @@
+---@diagnostic disable: undefined-global
+-- see https://pandoc.org/lua-filters.html
+return {
+	Link = function(link)
+		-- set target="_blank" for outgoing links (open them in new tab)
+		if string.match(link.target, "gzr.im") == nil then
+			table.insert(link.attributes, { "target", "_blank" })
+		end
+		return link
+	end,
+	Pandoc = function(doc)
+		local front = {}
+
+		-- add a comment
+		table.insert(
+			front,
+			pandoc.RawBlock(
+				"html5",
+				"<!-- Generated file, you may edit and discard "
+					.. pandoc.path.filename(PANDOC_STATE.input_files[1])
+					.. " :) -->"
+			)
+		)
+
+		local toc = pandoc.structure.table_of_contents(doc)
+		if doc.meta.toc and toc then
+			table.insert(front, pandoc.RawBlock("html5", '<nav class="table-of-contents capital">'))
+			table.insert(front, pandoc.RawBlock("html5", "<ol>"))
+			-- insert jump to top
+			table.insert(front, pandoc.RawBlock("html5", "<li>"))
+			table.insert(front, pandoc.Link("back to top", "#top"))
+			table.insert(front, pandoc.RawBlock("html5", "</li>"))
+			-- create custom toc
+			toc:walk({
+				Link = function(e)
+					table.insert(front, pandoc.RawBlock("html5", "<li>"))
+					table.insert(front, e)
+					table.insert(front, pandoc.RawBlock("html5", "</li>"))
+				end,
+			})
+			table.insert(front, pandoc.RawBlock("html5", "</ol>"))
+			table.insert(front, pandoc.RawBlock("html5", "</nav>"))
+		end
+
+		-- insert date blocks
+		if doc.meta.date then
+			table.insert(front, pandoc.RawBlock("html5", '<span class="date">'))
+			table.insert(front, doc.meta.date)
+			table.insert(front, pandoc.RawBlock("html5", "</span>"))
+		end
+
+		-- prepend front stuffs
+		for i = #front, 1, -1 do
+			table.insert(doc.blocks, 1, front[i])
+		end
+
+		-- return finished ast
+		return doc
+	end,
+}