import { createJiti } from "jiti"; import { mkdtempSync, copyFileSync, existsSync, readFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; const jiti = createJiti(import.meta.url, { interopDefault: true }); const R = "/home/moze/Sorgenti/pi-imgen"; const typst = await jiti.import(join(R, "extensions/imgen/render/typst.ts")); const cfgMod = await jiti.import(join(R, "extensions/imgen/config.ts")); const job = mkdtempSync(join(tmpdir(), "imgen-e2e-")); copyFileSync(join(R, "tests/art.png"), join(job, "art.png")); const cfg = { ...cfgMod.DEFAULTS, outputDir: job }; const spec = { slug: "sagra-castagna", format: "a3-portrait", template: "hero-bottom", palette: { bg: "#f4efe6", ink: "#101014", accent: "#b03a24", scrim: "#000000" }, fonts: { display: "Archivo", body: "Archivo" }, art: { prompt: "autumn chestnuts", negative: "text, letters", seed: 7, source: "generate" }, blocks: [ { role: "title", text: "Sagra della Castagna" }, { role: "date", text: "Sabato 12 settembre, ore 21:00" }, { role: "venue", text: "Chiostro di San Domenico, Città Alta" }, ], }; const resolved = await typst.resolveSpec(spec, cfg, join(job, "art.png"), { format: "a3-portrait" }); console.log("resolved.art_file =", resolved.art_file); console.log("resolved.ink_on_art =", resolved.ink_on_art); console.log("resolved.ink_on_bg =", resolved.ink_on_bg); console.log("resolved.needs_scrim =", resolved.needs_scrim); console.log("resolved.page =", JSON.stringify(resolved.page)); console.log("resolved.font_axes =", JSON.stringify(resolved.font_axes)); const TY = process.env.TYPST; const out = join(job, "poster.pdf"); await typst.renderOne(resolved, job, out, { binary: TY }); const d = readFileSync(out); const tb = /\/TrimBox\s*\[([^\]]*)\]/.exec(d.toString("latin1")); if (!tb) { console.log("TrimBox: ABSENT"); process.exit(1); } const [x0,y0,x1,y1] = tb[1].split(/\s+/).map(Number); console.log(`TrimBox mm = ${((x1-x0)/72*25.4).toFixed(1)} x ${((y1-y0)/72*25.4).toFixed(1)}`); console.log("bundle staged =", existsSync(join(job, ".typst/lib.typ")), existsSync(join(job, ".typst/hero-bottom.typ"))); // The request-shaped API is what the commands actually call. const outcome = await typst.render({ spec, artPath: join(job, "art.png"), outDir: job, config: cfg, formats: ["a3-portrait", "ig-story"], pdf: true, onProgress: (m) => console.log(" progresso:", m), }); console.log("files =", outcome.files.map(f => f.split("/").pop()).join(", ")); console.log("warnings =", outcome.warnings ?? "(nessuno)"); console.log("OK");