@commentware-private/documents exports the functions that define a template
and render it to a PDF or an XLSX file.
The library is experimental, so a function may change or be removed in any release, with no notice first. A project imports each by that name. react, react-dom, zod and exceljs
are peers: a template builds its elements, schema and workbook with the
project’s own copies, so the project installs them beside the library.
defineTemplate
Usage: defineTemplate({ schema, supportedOutputs, mockData, config })
Defines a template. A template file’s default export is its result.
schemais a zod schema for the params. Every render checks the params against it.supportedOutputslists"pdf","xlsx"or both. A template that lists"xlsx"also renders to"pdf", printed from its workbook.mockDatais params the schema accepts, which the preview starts from.config({ params })answers the template’smetadataandrenderersfor those params:metadata.fileNameis the file’s name without its extension.metadata.pdfis{ name, width, height, margin? }, the page as CSS lengths inmm,cm,in,ptorpx, andmarginis{ top?, right?, bottom?, left? }in the same lengths, each0by default. A template with a component needsmetadata.pdf. Every page of the PDF is exactly this size.metadata.xlsxis{ sheetName?, pdf? }, wherepdflays the workbook out when it is printed:fitis"scale-to-fit", the default, or"auto", andalignis"left", the default,"center"or"right". A printed workbook is on an A4 page with10mmmargins unlessmetadata.pdfnames another page.renderers.pdfis{ component }, wherecomponentis an async function returning the React element drawn on the page, or the result ofrenderXlsxToPdf.renderers.xlsxis{ workbook }, whereworkbookis an async function returning anexceljsworkbook.
This template builds a spreadsheet of SKUs and prices:
import ExcelJS from "exceljs";
import { z } from "zod";
import { defineTemplate, xlsxStyles } from "@commentware-private/documents";
export default defineTemplate({
schema: z.object({
items: z.array(z.object({ sku: z.string(), price: z.number() })),
}),
supportedOutputs: ["xlsx"],
mockData: { items: [{ sku: "WA-001", price: 29.99 }] },
config: async ({ params }) => ({
metadata: { fileName: "price-list", xlsx: { sheetName: "Prices" } },
renderers: {
xlsx: {
workbook: async () => {
const workbook = new ExcelJS.Workbook();
const sheet = workbook.addWorksheet("Prices");
sheet.addRow(["SKU", "Price"]).font = xlsxStyles.headerRow.font;
for (const item of params.items) {
sheet.addRow([item.sku, item.price]).getCell(2).numFmt =
xlsxStyles.currency;
}
return workbook;
},
},
},
}),
});defineConfig
Usage: defineConfig({ templates, ... })
Types the default export of documents.config.ts. Every option is on
documents.config.ts.
createRenderer
Usage: createRenderer({ templates, stylesheet?, browser? })
Returns a renderer for a project’s templates. templates and stylesheet are
the two exports of the templates.ts that commentware-documents build
writes; browser is { executablePath? }, as in the config. The renderer’s
types know every template’s id, its params and its outputs, so a wrong one does
not compile.
render
Usage: renderer.render(id, params, output)
Renders one template to "pdf" or "xlsx" and answers { bytes, fileName, mimeType }, where fileName carries the extension. The first PDF starts
Chrome, which stays up until close.
Params the template’s schema does not accept are refused, with each problem at its path:
The params for "thank-you" do not match its schema:
✖ Invalid input: expected string, received number
→ at nameAn id no template has is refused with the ids there are, as in
No template has the id "thank-yuo". The templates are: price-list, thank-you.,
and an output the template does not render to with the ones it does, as in
"thank-you" does not render to xlsx. It renders to pdf.
metadata
Usage: renderer.metadata(id, params)
Answers the template’s metadata for those params, and every output it
renders to, without rendering it. For the price list above:
{
fileName: 'price-list',
xlsx: { sheetName: 'Prices' },
supportedOutputs: [ 'xlsx', 'pdf' ]
}close
Usage: renderer.close()
Stops the Chrome that PDFs are printed with. A later PDF starts it again.
renderXlsxToPdf
Usage: renderXlsxToPdf(workbook, options?)
Makes a template’s PDF a print of a workbook. workbook is an async function
returning an exceljs workbook, as renderers.xlsx.workbook is, and options
takes the same fit and align as metadata.xlsx.pdf. Use it as
renderers.pdf when the PDF prints a different workbook from the XLSX file:
pdf: renderXlsxToPdf(summaryWorkbook, { fit: "auto" }).
fetchAndAddImage
Usage: fetchAndAddImage(workbook, sheet, url, range, options?)
Fetches the image at url, converts an SVG to PNG because Excel draws no SVG,
fits it to the cell range, such as "A1:B3", and places it. options.fit is
"fill", the default, "contain" or "cover"; options.position places a
contained or covered image, "center" by default; options.editAs is
"twoCell", the default, "oneCell" or "absolute", as exceljs takes it. A
range that is not two cell addresses is refused, naming it.
addImageToWorksheet
Usage: addImageToWorksheet(workbook, sheet, { buffer, extension, range, editAs?, imageWidth?, imageHeight? })
Places image bytes the template already has, as a "png", "jpeg" or "gif",
on the cell range, unchanged. With editAs of "oneCell" or "absolute",
imageWidth and imageHeight in pixels keep Excel from stretching it.
xlsxStyles
Type: an object
Styles a workbook template reuses: headerRow, a bold font and a centered
alignment, and the number formats currency, percentage, date and
dateTime.