local function resolve(base, relative) if relative:sub(1, 1) == "/" then return relative end local combined = base .. "/" .. relative local segments = {} for segment in combined:gmatch("[^/]+") do if segment == ".." then if #segments > 0 and segments[#segments] ~= ".." then table.remove(segments) else table.insert(segments, "..") end elseif segment ~= "." and segment ~= "" then table.insert(segments, segment) end end local prefix = (base:sub(1, 1) == "/" or relative:sub(1, 1) == "/") and "/" or "" return prefix .. table.concat(segments, "/") end local buffer = "" local should_render = true local current_dir = "" -- Stores the directory prefix of the file being processed local current_file = "" function filter_open(...) local args = {...} current_file = args[1] or "" if current_file == "" then current_file = "README.md" end -- Strict route enforcement: Allow README.md OR any file starting with docs/ and ending in .md if current_file == "README.md" or (current_file:sub(1, 5) == "docs/" and current_file:sub(-3) == ".md") then should_render = true -- Extract directory context (e.g., "docs/ops.md" -> "docs/") -- If it's the root README.md, current_dir stays an empty string "" if current_file ~= "README.md" then current_dir = current_file:match("(.*/)") or "" else current_dir = "" end else should_render = false end buffer = "" end function filter_write(str) if should_render then buffer = buffer .. str end end function filter_close() if not should_render then io.write("

Error: Access Denied. Only README.md and documentation markdown files are viewable here.

") return end local repo = os.getenv("CGIT_REPO_URL") or "" local processed = buffer:gsub("%[([^%]]+)%]%(([^:)]+)%)", function(text, path) -- Ignore protocols (http, https, etc.), absolute paths (/), and anchors (#) if path:sub(1, 1) == "/" or path:sub(1, 1) == "#" or path:match("^%w+:") then return string.format("[%s](%s)", text, path) end local fragment path, fragment = path:match("^([^#]*)(.*)$") path = resolve(current_dir, path) if path:sub(-3) == ".md" then return string.format("[%s](/%s/about/%s%s)", text, repo, path, fragment) else return string.format("[%s](/%s/tree/%s%s)", text, repo, path, fragment) end end) -- Pipe everything into md2html local handle = io.popen("@md2html@ --github", "w") if handle then handle:write(processed) handle:close() else io.write("

Error: Could not execute md2html.

") end end