Does anybody knows if there is a build step somewhere to convert a markdown document to a man page (groff/troff)?
I had a cursory look but coudn’t find anything.
Does anybody knows if there is a build step somewhere to convert a markdown document to a man page (groff/troff)?
I had a cursory look but coudn’t find anything.
Generic answer would be:
No need install anything system wide, these days, you can use zig build system to fetch a binary directly.
I think pandoc can do markdown to manages conversion, so you can actually more or less directly re-use setup described in
build.zig.zon:
.{
.name = "Build Zig Docs",
.version = "0.0.0",
.dependencies = .{
.pandoc_macos_arm64 = .{
.url = "https://github.com/jgm/pandoc/releases/download/3.4/pandoc-3.4-arm64-macOS.zip",
.hash = "1220c2506a07845d667e7c127fd0811e4f5f7591e38ccc7fb4376450f3435048d87a",
.lazy = true,
},
.pandoc_linux_amd64 = .{
.url = "https://github.com/jgm/pandoc/releases/download/3.4/pandoc-3.4-linux-amd64.tar.gz",
.hash = "1220139a44886509d8a61b44d8b8a79d03bad29ea95493dc97cd921d3f2eb208562c",
.lazy = true,
},
},
.paths = .{"."},
}
build.zig:
const std = @import("std");
const builtin = @import("builtin");
const os = builtin.os;
const cpu = builtin.cpu;
const assert = std.debug.assert;
pub fn build(b: *std.Build) !void {
const pandoc_dependency = if (os.tag == .linux and cpu.arch == .x86_64)
b.lazyDependency("pandoc_linux_amd64", .{}) orelse return
else if (os.tag == .macos and cpu.arch == .aarch64)
b.lazyDependency("pandoc_macos_arm64", .{}) orelse return
else
return error.UnsupportedHost;
const pandoc = pandoc_dependency.path("bin/pandoc");
const website = b.addWriteFiles();
const markdown_files = b.run(&.{ "git", "ls-files", "content/*.md" });
var lines = std.mem.tokenizeScalar(u8, markdown_files, '\n');
while (lines.next()) |file_path| {
const markdown = b.path(file_path);
const html = markdown2html(b, pandoc, markdown);
var html_path = file_path;
html_path = cut_prefix(html_path, "content/").?;
html_path = cut_suffix(html_path, ".md").?;
html_path = b.fmt("{s}.html", .{html_path});
_ = website.addCopyFile(html, html_path);
}
b.installDirectory(.{
.source_dir = website.getDirectory(),
.install_dir = .prefix,
.install_subdir = ".",
});
}
fn markdown2html(
b: *std.Build,
pandoc: std.Build.LazyPath,
markdown: std.Build.LazyPath,
) std.Build.LazyPath {
const pandoc_step = std.Build.Step.Run.create(b, "run pandoc");
pandoc_step.addFileArg(pandoc);
pandoc_step.addArgs(&.{ "--from=markdown", "--to=html5" });
pandoc_step.addFileArg(markdown);
return pandoc_step.captureStdOut();
}
fn cut_prefix(text: []const u8, prefix: []const u8) ?[]const u8 {
if (std.mem.startsWith(u8, text, prefix)) return text[prefix.len..];
return null;
}
fn cut_suffix(text: []const u8, suffix: []const u8) ?[]const u8 {
if (std.mem.endsWith(u8, text, suffix)) return text[0 .. text.len - suffix.len];
return null;
}
I ported the excellent scdoc to zig for almost this exact purpose. Scdoc syntax is not exactly the same as markdown, but it’s close and pretty tailored to manpages
More details for those interested: Introducing scdoc, a man page generator