Paradoc
SDKRenderers

textRenderer

Last updated on

Render Paradoc artifacts to text-based formats

Render forms to HTML, Markdown, or plain text with Paradoc's deterministic template syntax. It supports interpolation, nested paths, conditionals, loops, context blocks, and helpers without executing arbitrary JavaScript. Field values are automatically serialized from their schema types.

Example

import { para } from '@paradoc/core'
import { textRenderer } from '@paradoc/render/text'

const form = para.form({
  name: 'receipt',
  fields: {
    customer: { type: 'text', label: 'Customer' },
    total: { type: 'money', label: 'Total' },
    date: { type: 'date', label: 'Date' }
  },
  layers: {
    html: {
      kind: 'inline',
      mimeType: 'text/html',
      text: `
        <h1>Receipt</h1>
        <p>Customer: {{customer}}</p>
        <p>Total: {{total}}</p>
        <p>Date: {{date}}</p>
      `
    }
  },
  defaultLayer: 'html'
})

// Fill the form with data
const filled = form.fill({
  fields: {
    customer: 'Acme Corp',
    total: { amount: 250.00, currency: 'USD' },
    date: '2024-03-15'
  }
})

// Render the filled form
const output = await filled.render({
  renderer: textRenderer()
})
// Output:
// <h1>Receipt</h1>
// <p>Customer: Acme Corp</p>
// <p>Total: $250.00</p>
// <p>Date: March 15, 2024</p>

Import

From the unified package's text entry point:

import { textRenderer } from '@paradoc/render/text'

API

textRenderer()

Factory function that creates a configured text renderer instance.

function textRenderer(options?: TextRendererOptions): ParadocRenderer<
  RendererLayer & { type: 'text'; content: string },
  string
>

Parameters

options?: TextRendererOptions
Configuration options

TextRendererOptions

serializers?: SerializerRegistry
Custom serializer registry for formatting field values. Defaults to USA serializers.
signatureOptions?: TextSignatureOptions
Options for signature and initials template marker rendering.

TextSignatureOptions

format?: 'text' | 'html' | 'markdown'
Output format for signatures. Defaults to "text".
placeholder?: { signature?: string | Function, initials?: string | Function }
Placeholder text/function for unsigned signatures and initials.
captured?: { signature?: string | Function, initials?: string | Function }
Text/function for captured signatures and initials.
altText?: string
Alt text for signature images (html format only).
cssClass?: string
CSS class for signature images (html format only).

Returns

Returns an ParadocRenderer object with:

id: "text"
Renderer identifier
Methods
render: (request: RenderRequest) => string
Render function that returns the populated template string

renderText()

Low-level function for direct template rendering without the full renderer interface.

function renderText(options: {
  template: string
  data: Record<string, unknown>
  form?: Form
  serializers?: SerializerRegistry
  bindings?: Bindings
  signatureOptions?: TextSignatureOptions
}): string

Parameters

template: string
Paradoc template string
data: Record<string, unknown>
Data object to populate the template
form?: Form
Form schema for automatic field type detection and serialization
serializers?: SerializerRegistry
Custom serializer registry. Defaults to USA serializers.
bindings?: Bindings
Mapping from template placeholders to data keys
signatureOptions?: TextSignatureOptions
Options for signature and initials rendering

Returns

Returns the rendered template as a string.

Automatic Serialization

When a form schema is provided, field values are automatically serialized based on their types:

const form = para.form({
  name: 'demo',
  fields: {
    price: { type: 'money' },
    percentage: { type: 'percentage' },
    phone: { type: 'phone' }
  },
  layers: {
    text: { kind: 'inline', mimeType: 'text/plain', text: '{{price}} {{percentage}} {{phone}}' }
  }
})

const filled = form.fill({
  fields: {
    price: { amount: 99.99, currency: 'USD' },
    percentage: 0.15,
    phone: { e164: '+14155551234' }
  }
})

const output = await filled.render({
  renderer: textRenderer()
})
// output: "$99.99 15% (415) 555-1234"

Custom Serializers

Use custom serializers for different locales or formatting preferences:

import { textRenderer } from '@paradoc/render/text'
import { euSerializers } from '@paradoc/serialization'

const renderer = textRenderer({
  serializers: euSerializers
})

// Money formatted as "99,99 €" instead of "$99.99"

Template Bindings

Use bindings to map template placeholders to different field names:

const form = para.form({
  name: 'contract',
  fields: {
    buyerFullName: { type: 'text' }
  },
  layers: {
    text: {
      kind: 'inline',
      mimeType: 'text/plain',
      text: 'Buyer: {{buyer_name}}',
      bindings: {
        buyer_name: 'buyerFullName'  // Maps {{buyer_name}} to buyerFullName field
      }
    }
  }
})

Signature and Initials Helpers

The text renderer includes helpers for rendering signature and initials markers in templates.

Template Syntax

{{signature "locationId"}}  - Renders a signature placeholder or captured status
{{initials "locationId"}}   - Renders an initials placeholder or captured status

The locationId identifies where in the document the signature appears (e.g., "final-sig", "page-3-init"). The helpers automatically infer the party role, party ID, and signer ID from the template context.

Important: These helpers must be used inside a party or signatories loop to provide context.

Example with Signatures

const form = para.form({
  name: 'lease',
  fields: { /* ... */ },
  parties: {
    tenant: { label: 'Tenant', signature: { required: true } },
    landlord: { label: 'Landlord', signature: { required: true } }
  },
  layers: {
    html: {
      kind: 'inline',
      mimeType: 'text/html',
      text: `
        <h1>Lease Agreement</h1>

        <h2>Tenants</h2>
        {{#each parties.tenant}}
        <p>Name: {{name}}</p>
        <p>Signature: {{signature "final-sig"}}</p>
        <p>Initials: {{initials "page-init"}}</p>
        {{/each}}

        <h2>Landlord</h2>
        {{#each parties.landlord.signatories}}
        <p>{{signer.person.name}}, {{capacity}}</p>
        <p>Signature: {{signature "final-sig"}}</p>
        {{/each}}
      `
    }
  }
})

// Render with signature options
const output = await form.fill(data).render({
  renderer: textRenderer({ signatureOptions: { format: 'html' } })
})

Output Formats

FormatUnsignedSigned (with image)
text[SIGNATURE REQUIRED][Signature captured]
html<span class="signature-placeholder">...</span><img src="data:..." alt="Signature" class="signature-image" />
markdown_[SIGNATURE REQUIRED]_![Signature](data:...)

Related

On this page