process.js is plain JavaScript that runs after validate.js passes. It declares each output page, places layout files on them, and can add or adjust blocks. It is required: a project with no process.js, or one that never declares a page, generates nothing. It runs once, top to bottom.

addPage({ width: 210, height: 297, backgroundColor: "#FFFFFF" }); // page 1

overlay("overlay.canvas");
if (inputs["is_certified"]) {
  overlay("certified_badge.canvas");   // only when the checkbox is on
}

inputs is the submitted form values, plus inputs.uid and inputs.timestamp. Assign new properties (or reassign existing ones) to hand computed values to blocks, which read them as {inputs.name}. A block sees inputs as it was when its layout was placed. Set inputs.output_base_filename to name the generated file. Local variables (var x) never reach a block; only inputs does.

Pages and layouts

Function Does
addPage({width, height, backgroundColor}) A blank page. Anything omitted uses project.ypf's page defaults.
addPage({pdf, pdfPage, width, height}) A page backed by page pdfPage (default 1) of a PDF in the project.
overlay(file[, page[, transform]]) Places a .canvas file on page (default 1). transform is {dx, dy, rotate, align_top, align_bottom}, all optional.
setPageWidth(page, mm), setPageHeight(page, mm) Set a page's size.
setPageScale(page, x[, y]), setDocScale(x[, y]) Scale a page, or the whole document, about the upper-left corner; the page size scales too (1.1 turns 210 x 297 into 231 x 326.7). y defaults to x; no arguments clears it.

Pages are numbered by the order of the addPage calls, and must exist before you target them.

Adding and reading blocks

Function Does
addBlock(page, blockDef[, overlayHandle[, newHandle]]) Adds a block from a flat block object (the same shape as one entry of placements; an optional handle names it). With overlayHandle, it goes inside that canvas overlay block; a grid overlay refuses it (use setCells). Returns the block's path.
getBlockInfo(path) A block's resolved properties plus its path. A path is dotted through nested overlays ("table.price"); a number is a 1-based position for a block with no handle; doc.{page}... is the page-rooted form.
getBlocks(baseName) Every block sharing that handle (item, item~2, ...) as getBlockInfo objects, or [].
setVisible(path, bool) Hides or shows a block. It keeps its space but is not drawn (unlike condition, which stops it being built).
setTransform(path, transform) Sets an overlay block's transform: rotate, scale_x, scale_y, skew_x, skew_y, pivot_align, pivot_valign, or matrix (a full 4x4, 16 numbers column-major, used instead of those). null clears it.
getBlockBounds(page) {x, y, width, height} covering the page's blocks so far, or null.

A grid child's x, y, width and height in getBlockInfo are where the grid lays it out right now. See Grid.

A block's handle is optional (lowercase letters and digits with single _ or - separators, not all digits, never doc); an overlay block requires one. Duplicate handles among siblings become name~2, name~3.

Grid cells

Function Does
getCount(grid) Number of cell slots now, blank ones included.
getCells(source, start[, count]) Cells from a grid's handle or an assets:name.grid file; null for a blank slot.
setCells(grid, start, cells) Writes an array of cells from slot start (1-based); null clears a slot. On a repeating-group grid the record cells are already expanded, so setCells(grid, getCount(grid) + 1, [...]) appends after them.
orderCells(grid, start, end, direction), orderOrows(...), orderOcols(...) Reorder cells, lanes or columns in that range by whether they hold data: "asc" puts those without data first, "desc" puts data first.

Project and formatting helpers

Function Returns
getProject() {name, description, notes, categories, defaultWidth, defaultHeight, defaultBackgroundColor}
listAssets() {images, fonts, pdfs, overlays}: the project's files.
getFormFields() The form's field definitions.
getImageDimensions(file) {width, height} in pixels, or null.
getPageSize(page), getPdfPageSize(file, page) {width, height} in mm.
formatNumber(value, decimals), formatCurrency(value, code), formatDate(value, pattern) Formatted strings. There is no Intl in the script engine.

To fit a page to its content, for example a receipt:

var b = getBlockBounds(1);
setPageHeight(1, b.y + b.height + 5);

console.log() and console.error() write to the debug log; an error stops the script.