Renderer ReferenceLast updated on
Last updated on
Render artifacts to different output formats
Renderers transform Paradoc artifacts into output formats like text, PDF, and DOCX. Each renderer implements the ParadocRenderer interface, making it easy to build custom renderers for your specific needs.
Installation
@paradoc/core uses the unified renderer automatically. Install it directly
when building custom integrations or using format-specific functions:
npm install @paradoc/renderUsage
import { p } from '@paradoc/core'
// Create a form with a template layer
const form = p.form({
name: 'invoice',
fields: {
customer: { type: 'text', label: 'Customer' },
total: { type: 'money', label: 'Total' }
},
layers: {
text: {
kind: 'inline',
mimeType: 'text/plain',
text: 'Invoice for {{fields.customer}}\nTotal: {{fields.total}}'
}
},
defaultLayer: 'text'
})
// Fill the form with data
const filled = form.fill({
fields: {
customer: 'Acme Corp',
total: { amount: 1500, currency: 'USD' }
}
})
// Render the filled form
const output = await filled.render()
// output: "Invoice for Acme Corp\nTotal: $1,500.00"Use the optional renderer property to override the default for one call:
const output = await filled.render({ renderer: myRenderer })The same optional override is available to .seal({ renderer: myRenderer }).
Paradoc still applies its built-in PDF flattening and canonical hashing after
the custom renderer or conversion adapter returns.
Renderer registry
render(), seal(), assemble(), and sealBundle() also take renderers,
a RendererRegistry keyed by layer MIME type. Core consults it when no
renderer override is given and before its built-in engines. This is how a
format core does not ship reaches the render call.
React layers (text/tsx and text/jsx) render this way. The renderer lives in
@paradoc/react-pdf, and reactLayerRenderers builds the entries for both MIME
types:
import { reactLayerRenderers } from '@paradoc/react-pdf'
const pdf = await filled.render({
layer: 'composition',
renderers: reactLayerRenderers({ components: { 'purchase-order.tsx': PurchaseOrder } }),
})The React renderer writes the PDF itself, so sealing a React layer needs no seal adapter. See @paradoc/react for the component side.
Format Entry Points
createLayerRenderer() is the default application entry point. Import a format subpath
when you need its low-level functions or format-specific configuration.
| Entry point | Description |
|---|---|
| Text | Deterministic text templating for HTML, Markdown, plain text |
| Fill PDF forms with AcroForm field support | |
| DOCX | Generate Word documents from templates |
@paradoc/render/pdf also exports PDF utilities: inspectPdf,
flattenPdf, selectPdfPages, mergePdfs, and the placement helpers. See
PDF utilities.
createLayerRenderer()
function createLayerRenderer(options?: CreateLayerRendererOptions): ParadocRenderer<
RendererLayer,
string | Uint8Array
>Renderer Interface
All renderers implement the ParadocRenderer interface. Use this to build custom renderers:
import type { ParadocRenderer, RenderRequest, RendererLayer } from '@paradoc/types'
const myRenderer: ParadocRenderer<RendererLayer, string> = {
id: 'my-renderer',
render(request: RenderRequest): string {
// Narrow on `kind` to read the artifact with its payload.
if (request.kind !== 'form') return String(request.template.content ?? '')
const { template, artifact, data } = request
// Your rendering logic here
return processTemplate(template.content, artifact, data)
}
}ParadocRenderer
RenderRequest
The request object passed to the render method. It names the artifact that declares the layer and carries the payload of that artifact's kind. Narrow on kind to read them:
kind | artifact | data |
|---|---|---|
form | Form | FormData: fields holds field values only; parties, annexes, signers, captures and computed defs travel beside it |
checklist | Checklist | ChecklistData: item statuses keyed by item ID, null when unset |
document | Document | none: a document has content, not data |
RendererLayer
The resolved template content:
ParadocRendererContext
Optional context for customizing renderer behavior. A key it does not declare is a type error:
Building Custom Renderers
To create a custom renderer:
- Implement the
ParadocRendererinterface - Handle the template type(s) you support
- Use the request formatter for consistent value presentation
import type { ParadocRenderer, RenderRequest, RendererLayer } from '@paradoc/types'
// Custom CSV renderer example
export function csvRenderer(): ParadocRenderer<
RendererLayer & { type: 'text'; content: string },
string
> {
return {
id: 'csv',
render(request: RenderRequest) {
if (request.kind !== 'form') throw new Error('The CSV renderer renders forms only')
const { artifact, data } = request
// Generate CSV from form fields and data
const headers = Object.keys(artifact.fields || {})
const values = headers.map(key => {
const value = data.fields?.[key]
return value != null ? String(value) : ''
})
return [headers.join(','), values.join(',')].join('\n')
}
}
}Related
- Formatting - Value formatting for renderers
- Form Layers - Template layer configuration