/**
* Output-format gate for `--to html` and `--to docx` (eng-review P7/P8),
* driven through the compiled binary against the diagram-gate fixture
* (diagrams + relative image + broken fence + render=false fence).
*
* HTML contract: ONE self-contained file — zero network references, no
* scripts, diagrams as inline SVG, images as data URIs, screen media layer.
*
* DOCX contract: content fidelity, not layout fidelity — valid OOXML zip,
* document.xml carries headings/code/diagnostics, diagrams embedded as PNG
* media. (A .docx is a zip: unzip -p is the oracle.)
*/
import { describe, expect, test } from "bun:test";
import { execFileSync } from "node:child_process";
import * as fs from "node:fs";
import * as path from "node:path";
const FIXTURE = path.resolve(__dirname, "../fixtures/diagram-gate.md");
const ROOT = path.resolve(__dirname, "../../..");
const PDF_BIN = path.join(ROOT, "make-pdf/dist/pdf");
const BROWSE_BIN = path.join(ROOT, "browse/dist/browse");
const BUNDLE = path.join(ROOT, "lib/diagram-render/dist/diagram-render.html");
const CHILD_TIMEOUT_MS = 60_000;
function prerequisitesAvailable(): { ok: true } | { ok: false; reason: string } {
if (!fs.existsSync(PDF_BIN)) return { ok: false, reason: `make-pdf binary missing (${PDF_BIN}). Run bun run build.` };
if (!fs.existsSync(BROWSE_BIN)) return { ok: false, reason: `browse binary missing (${BROWSE_BIN}).` };
if (!fs.existsSync(BUNDLE)) return { ok: false, reason: `diagram-render bundle missing (${BUNDLE}).` };
if (!fs.existsSync(FIXTURE)) return { ok: false, reason: `fixture missing (${FIXTURE}).` };
if (!Bun.which("unzip")) return { ok: false, reason: "unzip not found (needed for docx zip checks)." };
return { ok: true };
}
function generate(to: string, outputPath: string): void {
execFileSync(PDF_BIN, ["generate", FIXTURE, outputPath, "--quiet", "--to", to], {
encoding: "utf8",
env: { ...process.env, BROWSE_BIN },
stdio: ["ignore", "pipe", "pipe"],
timeout: CHILD_TIMEOUT_MS,
});
}
describe("output format gate", () => {
const avail = prerequisitesAvailable();
test.skipIf(!avail.ok)("--to html: single self-contained file, zero network refs", () => {
if (!avail.ok) return;
const workDir = fs.mkdtempSync("/tmp/make-pdf-format-html-");
const out = path.join(workDir, "out.html");
try {
generate("html", out);
const html = fs.readFileSync(out, "utf8");
// Zero network references and zero scripts. (The only http(s) tokens
// allowed are XML namespace identifiers inside inline SVG, which are
// never fetched.)
const refs = html.match(/\b(?:src|href)\s*=\s*"https?:[^"]*"/gi) ?? [];
expect(refs).toEqual([]);
expect(html).not.toMatch(/