Add the Neutral template family, template picker and text-only logo allowances
Linea (the vendor's original format.pdf design), Monogram and Serenity are rebuilt from the reference PDFs as one parametric family on the engine, with the user's logo in the measured slot, a home for every GST field and A4/Letter support. Adds static Montserrat, Open Sans and Poppins fonts and a generated Ms Madi outline for Serenity's vertical word. Text-only logo placeholders (Monolith, Tangerine) use a doc-derived allowance box. A Carbon TemplatePicker with committed thumbnails opens from the page setup controls.
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
// Renders every registered template with one fixed sample invoice into public/templates/<id>.png, the
|
||||
// static thumbnails of the template picker. Run: npm run thumbnails (the PNGs are committed).
|
||||
// The sample is the harness's tax invoice with The sample vendor's logo; the picker says that thumbnails use sample data.
|
||||
import { mkdirSync, writeFileSync } from "node:fs";
|
||||
import path from "node:path";
|
||||
import { ROOT, loadRenderer, rasterize } from "./templates/lib.mjs";
|
||||
|
||||
const OUT = path.join(ROOT, "public", "templates");
|
||||
const WIDTH = 420;
|
||||
const A4_WIDTH_PT = 595.28;
|
||||
|
||||
const ITEMS = [
|
||||
["Voice-over narration", 4, 1500],
|
||||
["Audio mastering", 2, 800],
|
||||
].map(([description, quantity, rate], i) => ({
|
||||
id: i + 1,
|
||||
description,
|
||||
mode: "rate",
|
||||
rate,
|
||||
unit: "hour",
|
||||
quantity,
|
||||
amount: 0,
|
||||
sortOrder: i,
|
||||
hsnSac: "998397",
|
||||
}));
|
||||
|
||||
const SAMPLE = {
|
||||
name: "thumbnail",
|
||||
items: ITEMS,
|
||||
logo: "real",
|
||||
signature: false,
|
||||
// A leaner supplier block keeps the whole design (closing block included) on the thumbnail's one page.
|
||||
vendor: { vendorEmail: "", vendorPhone: "", vendorPan: "" },
|
||||
invoice: { poNumber: "", notes: "" },
|
||||
};
|
||||
|
||||
const r = await loadRenderer();
|
||||
r.ensureSetup();
|
||||
mkdirSync(OUT, { recursive: true });
|
||||
for (const id of Object.keys(r.TEMPLATES)) {
|
||||
const rendered = await r.renderFixture(SAMPLE, r.prefsFor("A4", { templateId: id }));
|
||||
const canvas = await rasterize(rendered.result.bytes, 1, WIDTH / A4_WIDTH_PT);
|
||||
const file = path.join(OUT, `${id}.png`);
|
||||
writeFileSync(file, canvas.toBuffer("image/png"));
|
||||
console.log(`${id}: ${canvas.width} x ${canvas.height} px, ${rendered.result.pages} page(s), ${rendered.result.issues.length} audit issue(s)`);
|
||||
}
|
||||
Reference in New Issue
Block a user