Skip to content

Commit bcfe861

Browse files
mdjekicclaude
andcommitted
Add Document Authoring Template Population example
This example demonstrates how to populate Document Authoring templates with dynamic data using a Mustache-like syntax. Features: - Simple placeholder replacement ({{variable}}) - Loops for arrays ({{#array}}...{{/array}}) - Conditionals ({{#condition}}, {{^negated}}) - Table row duplication for array data - Custom delimiters and default values - TypeScript with full type safety The library processes templates in three phases: loops, conditionals, and simple placeholders, all within a Document Authoring transaction for atomic updates. 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
1 parent bdf41bd commit bcfe861

18 files changed

Lines changed: 1662 additions & 0 deletions

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ Server-side PDF processing and manipulation:
8888
## AI & Document Generation
8989

9090
- [AI Document Assistant](https://github.com/PSPDFKit/ai-document-assistant-demo) — Natural language PDF interaction with AI
91+
- [Document Authoring Template Population](./web/document-authoring-template-population/) — TypeScript library for populating templates with data (placeholders, loops, conditionals, table rows)
9192
- [Document Generator (Vanilla JS)](./web/document-generator-vanillajs/) — Step-by-step PDF generation with Document Authoring SDK
9293

9394
---
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
node_modules/
2+
dist/
3+
.env
4+
.DS_Store
5+
*.log
Lines changed: 247 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,247 @@
1+
# Document Authoring Template Data Population
2+
3+
A TypeScript library for applying template data to [Nutrient Document Authoring](https://www.nutrient.io/sdk/document-authoring/) documents. Populate DOCX templates with dynamic data using a Mustache-like syntax for placeholders, loops, and conditionals.
4+
5+
## Features
6+
7+
- **📝 Simple Placeholders** - Replace `{{variable}}` with data values
8+
- **🔄 Loops** - Duplicate content for arrays using `{{#array}}...{{/array}}`
9+
- **✅ Conditionals** - Show/hide content with `{{#condition}}...{{/condition}}`
10+
- **❌ Negated Conditionals** - Invert conditions with `{{^condition}}...{{/condition}}`
11+
- **📊 Table Support** - Automatically duplicate table rows for array data
12+
- **⚙️ Custom Delimiters** - Configure your own placeholder syntax
13+
- **🎨 Formatting Preservation** - Maintains text formatting (bold, italic, fonts, etc.)
14+
- **🔧 TypeScript** - Full type safety and IDE autocomplete
15+
16+
## Prerequisites
17+
18+
- Node.js 18 or later
19+
- A Nutrient Document Authoring license key (optional - will show watermark without one)
20+
21+
## Getting Started
22+
23+
### Installation
24+
25+
```bash
26+
npm install
27+
```
28+
29+
### Running the Demo
30+
31+
```bash
32+
npm run dev
33+
```
34+
35+
Then open [http://localhost:3000](http://localhost:3000) in your browser.
36+
37+
## Usage
38+
39+
### Basic Example
40+
41+
```typescript
42+
import { applyTemplateData } from './src/index.ts';
43+
44+
// Your template data
45+
const templateData = {
46+
config: {
47+
delimiter: { start: '{{', end: '}}' },
48+
defaultValue: ''
49+
},
50+
model: {
51+
customerName: 'Acme Corporation',
52+
invoiceNumber: 'INV-2024-001',
53+
total: '$12,420.00',
54+
lineItems: [
55+
{ description: 'Web Development', quantity: '40', amount: '$6,000.00' },
56+
{ description: 'UI/UX Design', quantity: '20', amount: '$3,500.00' }
57+
]
58+
}
59+
};
60+
61+
// Apply template data to an open document
62+
await applyTemplateData(docInstance, templateData);
63+
```
64+
65+
### Template Syntax
66+
67+
#### Simple Placeholders
68+
69+
Replace with a value from your data model:
70+
71+
```
72+
Invoice Number: {{invoiceNumber}}
73+
Customer: {{customerName}}
74+
Total: {{total}}
75+
```
76+
77+
#### Loops
78+
79+
Duplicate content for each item in an array:
80+
81+
```
82+
{{#lineItems}}
83+
- {{description}}: {{amount}}
84+
{{/lineItems}}
85+
```
86+
87+
For tables, the loop duplicates rows:
88+
89+
```
90+
| Description | Quantity | Amount |
91+
|-------------|----------|--------|
92+
| {{#lineItems}}{{description}} | {{quantity}} | {{amount}}{{/lineItems}} |
93+
```
94+
95+
#### Conditionals
96+
97+
Show content only if a condition is true:
98+
99+
```
100+
{{#showDiscount}}
101+
*** SPECIAL DISCOUNT APPLIED ***
102+
Discount: {{discountAmount}}
103+
{{/showDiscount}}
104+
```
105+
106+
#### Negated Conditionals
107+
108+
Show content only if a condition is false:
109+
110+
```
111+
{{^isPaid}}
112+
*** PAYMENT DUE ***
113+
Please pay by {{dueDate}}
114+
{{/isPaid}}
115+
```
116+
117+
## Project Structure
118+
119+
```
120+
document-authoring-template-population/
121+
├── src/
122+
│ ├── index.ts # Main library export
123+
│ ├── lib/
124+
│ │ ├── DocumentTemplating.ts # Core templating engine
125+
│ │ ├── parser/
126+
│ │ │ └── TemplateParser.ts # Placeholder parsing
127+
│ │ ├── processors/
128+
│ │ │ ├── PlaceholderReplacer.ts # {{variable}} replacement
129+
│ │ │ ├── ConditionalProcessor.ts # Conditional logic
130+
│ │ │ └── LoopProcessor.ts # Array loop handling
131+
│ │ └── utils/
132+
│ │ ├── DataResolver.ts # Data access utilities
133+
│ │ └── ValidatorUtil.ts # Validation helpers
134+
│ └── types/
135+
│ └── index.ts # TypeScript type definitions
136+
├── index.html # Demo application
137+
├── package.json
138+
├── tsconfig.json
139+
├── vite.config.js
140+
└── README.md
141+
```
142+
143+
## How It Works
144+
145+
The library processes templates in three phases:
146+
147+
1. **Loop Processing** - Duplicates content (including table rows) for array data
148+
2. **Conditional Processing** - Shows or hides content based on boolean values
149+
3. **Placeholder Replacement** - Replaces simple `{{variable}}` placeholders with values
150+
151+
All operations happen within a Document Authoring transaction for atomic updates.
152+
153+
### Table Row Duplication
154+
155+
When a loop (`{{#array}}...{{/array}}`) is detected in a table row:
156+
157+
1. The library identifies the template row
158+
2. Creates new rows for each array item
159+
3. Replaces placeholders in each row with item data
160+
4. Preserves text formatting (font, size, bold, etc.)
161+
5. Removes the template row
162+
163+
**Note:** Cell-level formatting (borders, backgrounds) uses default styling as the Document Authoring API doesn't currently expose methods to copy these properties.
164+
165+
## API Reference
166+
167+
### `applyTemplateData(instance, data, options?)`
168+
169+
Applies template data to a Document Authoring instance.
170+
171+
**Parameters:**
172+
- `instance` - The Document Authoring document instance
173+
- `data` - Template data object containing:
174+
- `config.delimiter` - Placeholder delimiters (default: `{{ }}`)
175+
- `config.defaultValue` - Value for missing data (default: `''`)
176+
- `model` - Your data object
177+
- `options` - Optional configuration (currently unused)
178+
179+
**Returns:** `Promise<void>`
180+
181+
**Example:**
182+
183+
```typescript
184+
const data = {
185+
config: {
186+
delimiter: { start: '{{', end: '}}' },
187+
defaultValue: 'N/A'
188+
},
189+
model: {
190+
name: 'John Doe',
191+
items: [...]
192+
}
193+
};
194+
195+
await applyTemplateData(doc, data);
196+
```
197+
198+
## Customization
199+
200+
### Custom Delimiters
201+
202+
Use different placeholder syntax:
203+
204+
```typescript
205+
const data = {
206+
config: {
207+
delimiter: { start: '[[', end: ']]' } // Use [[variable]] instead
208+
},
209+
model: { ... }
210+
};
211+
```
212+
213+
### Default Values
214+
215+
Set a fallback for missing data:
216+
217+
```typescript
218+
const data = {
219+
config: {
220+
defaultValue: 'N/A' // Show 'N/A' instead of empty string
221+
},
222+
model: { ... }
223+
};
224+
```
225+
226+
## Known Limitations
227+
228+
- **Table Formatting**: New rows created by loops will have default borders/backgrounds as the API doesn't expose cell formatting properties
229+
- **Nested Loops**: Not currently supported
230+
- **Complex Expressions**: Only simple value lookups are supported (no calculations or filters)
231+
232+
## License
233+
234+
This example is licensed under the MIT License.
235+
236+
## Support
237+
238+
For issues with this example:
239+
- Create an issue in the [awesome-nutrient repository](https://github.com/PSPDFKit/awesome-nutrient/issues)
240+
241+
For Nutrient Document Authoring SDK support:
242+
- Visit [Nutrient Support](https://www.nutrient.io/support/)
243+
- Check the [Document Authoring documentation](https://www.nutrient.io/guides/document-authoring/)
244+
245+
## Contributing
246+
247+
Contributions are welcome! Please feel free to submit a Pull Request.

0 commit comments

Comments
 (0)