A deterministic TypeScript library for generating PDF contracts from Markdown templates with dynamic content substitution. Produces identical PDFs across all global environments - perfect for blockchain applications and distributed systems requiring consensus.
- 🌍 Global Consensus: Same input produces identical PDFs worldwide (tested across 8 different timezones/locales)
- 📝 Template-based: Use Markdown templates with placeholder variables
-
🔄 Conditional logic: Support for
{{#if}}
blocks and complex conditions - 💰 Smart formatting: Automatic currency, date, and percentage formatting
- 📄 Professional PDFs: Generate clean, formatted documents using pdfmake
- 🛡️ Type-safe: Full TypeScript support with comprehensive type definitions
- 🧪 Well-tested: 100% consensus verification across global environments
- 🌐 Cross-platform: Works in both Node.js and browser environments
npm install @escrow-protocol/contract-generator
import { EscrowContractGenerator } from "@escrow-protocol/contract-generator"
const template = `
# Contract Agreement
**Parties:**
- **Buyer**: {{format_party:parties.buyer}}
- **Seller**: {{format_party:parties.seller}}
**Amount**: {{format_currency:terms.amount,terms.currency}}
{{#if exists:terms.delivery_date}}
**Delivery Date**: {{format_date:terms.delivery_date}}
{{/if}}
`
const contractData = {
parties: {
buyer: {
name: "John Doe",
type: "Individual",
jurisdiction: "New York, USA",
address: "123 Main St, New York, NY"
},
seller: {
name: "Acme Corp",
type: "Corporation",
entity_type: "LLC",
jurisdiction: "Delaware, USA",
address: "456 Business Ave, Delaware, DE"
}
},
terms: {
amount: 50000,
currency: "USD",
delivery_date: "2024-12-31"
}
}
const generator = new EscrowContractGenerator(template)
// Generate PDF
const { pdfData, warnings } = await generator.generatePDF(contractData, {
pageSize: "A4",
margins: { top: 50, bottom: 50, left: 50, right: 50 }
})
// Save or serve the PDF
const blob = new Blob([pdfData], { type: "application/pdf" })
{{variable.path}} // Simple variable substitution
{{nested.object.property}} // Nested object access
{{array.0.property}} // Array index access
{{format_party:parties.buyer}} // Format party description
{{format_currency:amount,currency}} // Format currency with locale
{{format_date:delivery_date}} // Format date
{{doc_name:documents.contract}} // Get document name
{{#if exists:variable}}
Content to include if variable exists
{{/if}}
{{#if not_exists:variable}}
Content to include if variable doesn't exist
{{/if}}
{{#if variable == 'value'}}
Content if variable equals value
{{else}}
Alternative content
{{/if}}
new EscrowContractGenerator(template: string)
generatePDF(
data: any,
options?: PDFOptions
): Promise<{ pdfData: ArrayBuffer; warnings: string[] }>
Parameters:
-
data
: Contract data object with variables for template substitution -
options
: PDF generation options (optional)
Returns: Promise resolving to an object with:
-
pdfData
: ArrayBuffer containing the generated PDF -
warnings
: Array of warning messages for unresolved placeholders
interface PDFOptions {
margins?: {
top?: number
right?: number
bottom?: number
left?: number
}
defaultStyle?: {
font?: string
fontSize?: number
lineHeight?: number
}
pageSize?: string // Default: 'A4'
pageOrientation?: "portrait" | "landscape" // Default: 'portrait'
header?: (currentPage: number, pageCount: number) => Content
footer?: (currentPage: number, pageCount: number) => Content
watermark?: string
callback?: (pdfData: ArrayBuffer) => void
}
npm run build
# Run basic tests
npm test
# Run comprehensive consensus tests (8 global environments)
npm run test:consensus
# Run all tests
npm run test:all
This library has been specifically designed and tested to produce identical PDF outputs regardless of:
- Timezone (tested across 8 different zones: US, UK, Japan, Germany, Australia, Brazil, India, Russia)
- System locale settings
- Operating system
- Node.js vs browser environment
For more details, see CONSENSUS_FIX.md.
MIT License - see LICENSE file for details.