@zola_do/docx 0.2.5 → 0.2.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +387 -26
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,7 +1,20 @@
1
1
  # @zola_do/docx
2
2
 
3
+ [![npm version](https://img.shields.io/npm/v/@zola_do/docx.svg)](https://www.npmjs.com/package/@zola_do/docx)
4
+ [![npm downloads](https://img.shields.io/npm/dm/@zola_do/docx.svg)](https://www.npmjs.com/package/@zola_do/docx)
5
+ [![License: ISC](https://img.shields.io/badge/License-ISC-blue.svg)](https://opensource.org/licenses/ISC)
6
+
3
7
  DOCX template processing for NestJS using docx-templates.
4
8
 
9
+ ## Overview
10
+
11
+ `@zola_do/docx` provides:
12
+
13
+ - **Template Population** — Fill DOCX templates with data
14
+ - **Placeholder Validation** — Check for required placeholders
15
+ - **Handlebars Syntax** — Supports loops, conditionals, images
16
+ - **Buffer Output** — Returns generated DOCX as Buffer
17
+
5
18
  ## Installation
6
19
 
7
20
  ```bash
@@ -12,13 +25,43 @@ npm install @zola_do/docx
12
25
  npm install @zola_do/nestjs-shared
13
26
  ```
14
27
 
15
- ## Usage
28
+ ### Dependencies
29
+
30
+ ```bash
31
+ npm install docx-templates
32
+ ```
33
+
34
+ ## Quick Start
16
35
 
17
- ### Module Setup
36
+ ### 1. Create a Template
37
+
38
+ Create a Word document with placeholders:
39
+
40
+ ```docx
41
+ Dear {{name}},
42
+
43
+ Thank you for your order #{{orderNumber}}.
44
+
45
+ Order Details:
46
+ {{#each items}}
47
+ - {{this.name}}: ${{this.price}}
48
+ {{/each}}
49
+
50
+ Total: ${{total}}
51
+
52
+ {{#if isPremium}}
53
+ As a premium member, you get 10% off your next order!
54
+ {{/if}}
55
+
56
+ Best regards,
57
+ {{companyName}}
58
+ ```
59
+
60
+ ### 2. Register Module
18
61
 
19
62
  ```typescript
20
- import { Module } from '@nestjs/common';
21
- import { DocxModule } from '@zola_do/docx';
63
+ import { Module } from "@nestjs/common";
64
+ import { DocxModule } from "@zola_do/docx";
22
65
 
23
66
  @Module({
24
67
  imports: [DocxModule],
@@ -26,54 +69,372 @@ import { DocxModule } from '@zola_do/docx';
26
69
  export class AppModule {}
27
70
  ```
28
71
 
29
- ### Generating Documents
30
-
31
- Fill a DOCX template with data. Use `{placeholder}` syntax in your Word document:
72
+ ### 3. Generate Document
32
73
 
33
74
  ```typescript
34
- import { Injectable } from '@nestjs/common';
35
- import { DocxService } from '@zola_do/docx';
75
+ import { Injectable } from "@nestjs/common";
76
+ import { DocxService } from "@zola_do/docx";
36
77
 
37
78
  @Injectable()
38
79
  export class ReportService {
39
80
  constructor(private readonly docxService: DocxService) {}
40
81
 
41
- async generateReport(templateBuffer: Buffer, data: Record<string, any>) {
42
- // Template contains {name}, {date}, etc.
43
- const result = await this.docxService.generateDocx(templateBuffer, data);
82
+ async generateInvoice(order: Order) {
83
+ const templateBuffer = await this.loadTemplate("invoice.docx");
84
+
85
+ const result = await this.docxService.generateDocx(templateBuffer, {
86
+ name: order.customerName,
87
+ orderNumber: order.number,
88
+ items: order.items,
89
+ total: order.total,
90
+ isPremium: order.customer.isPremium,
91
+ companyName: "My Company",
92
+ });
93
+
44
94
  return result; // Buffer of filled DOCX
45
95
  }
46
96
  }
47
97
  ```
48
98
 
49
- ### Validating Templates
99
+ ## Template Syntax
100
+
101
+ The package uses [docx-templates](https://github.com/guigrpa/docx-templates) for template rendering.
102
+
103
+ ### Basic Placeholders
104
+
105
+ ```handlebars
106
+ {{variableName}}
107
+
108
+ {{nested.property}}
109
+
110
+ {{array.index}}
111
+ ```
112
+
113
+ ### Conditionals
114
+
115
+ ```handlebars
116
+ {{#if condition}}
117
+ Content when true
118
+ {{else}}
119
+ Content when false
120
+ {{/if}}
121
+
122
+ {{#unless condition}}
123
+ Content when false
124
+ {{/unless}}
125
+ ```
126
+
127
+ ### Loops
128
+
129
+ ```handlebars
130
+ {{#each items}}
131
+ {{this.name}}
132
+ - ${{this.price}}
133
+ {{/each}}
134
+
135
+ {{#each orders}}
136
+ Order #{{this.number}}:
137
+ {{#each this.items}}
138
+ -
139
+ {{this.name}}
140
+ {{/each}}
141
+ {{/each}}
142
+ ```
143
+
144
+ ### Nested Data
145
+
146
+ ```handlebars
147
+ {{customer.name}}
148
+ {{customer.address.city}}
149
+ {{customer.address.zip}}
150
+ ```
151
+
152
+ ### Helpers
153
+
154
+ ```handlebars
155
+ {{uppercase name}}
156
+ {{lowercase email}}
157
+ {{formatDate date "MMMM YYYY"}}
158
+ {{currency amount}}
159
+ ```
160
+
161
+ ### Images
162
+
163
+ ```handlebars
164
+ {{#image filename width height}}
165
+ logo.png
166
+ {{/image}}
167
+
168
+ {{#imageUrl url width height}}
169
+ https://example.com/logo.png
170
+ {{/imageUrl}}
171
+ ```
172
+
173
+ ## Advanced Templates
174
+
175
+ ### Table with Rows
176
+
177
+ ```handlebars
178
+ | Product | Quantity | Price | |---------|----------|-------|
179
+ {{#each items}}
180
+ |
181
+ {{this.name}}
182
+ |
183
+ {{this.quantity}}
184
+ | ${{this.price}}
185
+ |
186
+ {{/each}}
187
+ | **Total** | | **${{total}}** |
188
+ ```
189
+
190
+ ### Nested Tables
191
+
192
+ ```handlebars
193
+ {{#each orders}}
194
+ Order #{{this.number}}
195
+ -
196
+ {{this.date}}
197
+
198
+ | Item | Qty | Price | |------|-----|-------|
199
+ {{#each this.items}}
200
+ |
201
+ {{name}}
202
+ |
203
+ {{qty}}
204
+ | ${{price}}
205
+ |
206
+ {{/each}}
207
+
208
+ ---
209
+ {{/each}}
210
+ ```
211
+
212
+ ### Conditional Sections
213
+
214
+ ```handlebars
215
+ {{#if hasDiscount}}
216
+ Original Price: ~~${{originalPrice}}~~ Discounted Price: ${{discountedPrice}}
217
+ {{else}}
218
+ Price: ${{price}}
219
+ {{/if}}
220
+ ```
221
+
222
+ ## Validation
223
+
224
+ ### Validate Document
225
+
226
+ Check that a template contains all required placeholders:
227
+
228
+ ```typescript
229
+ async validateInvoiceTemplate() {
230
+ const templateBuffer = await this.loadTemplate('invoice.docx');
231
+
232
+ const missingProps = await this.docxService.validateDocument(
233
+ templateBuffer,
234
+ ['name', 'orderNumber', 'items', 'total', 'companyName'],
235
+ );
236
+
237
+ if (missingProps.length > 0) {
238
+ throw new Error(`Missing placeholders: ${missingProps.join(', ')}`);
239
+ }
240
+ }
241
+ ```
242
+
243
+ ### Validation Result
244
+
245
+ ```typescript
246
+ interface ValidationResult {
247
+ missing: string[]; // Placeholders not in template
248
+ unused: string[]; // Data properties not in template
249
+ }
250
+ ```
251
+
252
+ ## Real-World Examples
50
253
 
51
- Ensure a template has all required placeholders before generating:
254
+ ### Invoice Generation
52
255
 
53
256
  ```typescript
54
- const missingProps = await this.docxService.validateDocument(
55
- templateBuffer,
56
- ['name', 'date', 'amount'],
57
- );
58
- if (missingProps.length > 0) {
59
- throw new Error(`Missing placeholders: ${missingProps.join(', ')}`);
257
+ async generateInvoice(orderId: string): Promise<Buffer> {
258
+ const order = await this.orderService.findOne(orderId);
259
+ const template = await this.loadTemplate('invoice.docx');
260
+
261
+ const data = {
262
+ invoiceNumber: order.invoiceNumber,
263
+ date: new Date().toLocaleDateString(),
264
+ customer: {
265
+ name: order.customer.name,
266
+ email: order.customer.email,
267
+ address: `${order.customer.address}\n${order.customer.city}, ${order.customer.zip}`,
268
+ },
269
+ items: order.items.map(item => ({
270
+ name: item.productName,
271
+ quantity: item.quantity,
272
+ price: item.unitPrice.toFixed(2),
273
+ subtotal: item.subtotal.toFixed(2),
274
+ })),
275
+ subtotal: order.subtotal.toFixed(2),
276
+ tax: order.tax.toFixed(2),
277
+ total: order.total.toFixed(2),
278
+ isPaid: order.status === 'PAID',
279
+ paymentInfo: order.paymentInfo,
280
+ };
281
+
282
+ return this.docxService.generateDocx(template, data);
60
283
  }
61
284
  ```
62
285
 
63
- ## Template Syntax
286
+ ### Certificate Generation
287
+
288
+ ```typescript
289
+ async generateCertificate(userId: string, courseId: string): Promise<Buffer> {
290
+ const [user, course] = await Promise.all([
291
+ this.userService.findOne(userId),
292
+ this.courseService.findOne(courseId),
293
+ ]);
294
+
295
+ const template = await this.loadTemplate('certificate.docx');
296
+
297
+ return this.docxService.generateDocx(template, {
298
+ recipientName: user.fullName,
299
+ courseName: course.name,
300
+ completionDate: new Date().toLocaleDateString('en-US', {
301
+ year: 'numeric',
302
+ month: 'long',
303
+ day: 'numeric',
304
+ }),
305
+ instructorName: course.instructor.name,
306
+ certificateId: generateCertificateId(),
307
+ companyName: 'My Organization',
308
+ logoPath: '/templates/logo.png',
309
+ });
310
+ }
311
+ ```
312
+
313
+ ## Template Preparation
314
+
315
+ ### Creating Templates
316
+
317
+ 1. Open Microsoft Word or LibreOffice
318
+ 2. Create a new document
319
+ 3. Add placeholders using `{{placeholderName}}` syntax
320
+ 4. Save as `.docx` format
321
+
322
+ ### Recommended Placeholder Names
323
+
324
+ ```handlebars
325
+ {{firstName}}
326
+ {{lastName}}
327
+ {{email}}
328
+ {{phone}}
329
+ {{address}}
330
+ {{city}}
331
+ {{orderNumber}}
332
+ {{orderDate}}
333
+ {{totalAmount}}
334
+ {{status}}
335
+ {{companyName}}
336
+ {{logoPath}}
337
+ ```
338
+
339
+ ### Testing Templates
340
+
341
+ ```typescript
342
+ const testData = {
343
+ name: "Test User",
344
+ orderNumber: "ORD-001",
345
+ items: [
346
+ { name: "Product A", price: 10 },
347
+ { name: "Product B", price: 20 },
348
+ ],
349
+ total: 30,
350
+ isPremium: false,
351
+ companyName: "Test Company",
352
+ };
353
+
354
+ const result = await docxService.generateDocx(templateBuffer, testData);
355
+ // Verify result is valid DOCX
356
+ ```
64
357
 
65
- Uses [docx-templates](https://github.com/guigrpa/docx-templates) syntax. Placeholders use `{variableName}`. Supports loops, conditionals, and images—see the docx-templates documentation.
358
+ ## API Reference
66
359
 
67
- ## Exports
360
+ ### Module
68
361
 
69
- - `DocxModule` — Register the DOCX module
70
- - `DocxService` — `generateDocx`, `validateDocument`
362
+ ```typescript
363
+ DocxModule.forRoot(options?: DocxModuleOptions)
364
+ ```
365
+
366
+ ### Service
367
+
368
+ ```typescript
369
+ class DocxService {
370
+ async generateDocx(
371
+ template: Buffer,
372
+ data: Record<string, any>,
373
+ ): Promise<Buffer>;
374
+
375
+ async validateDocument(
376
+ template: Buffer,
377
+ requiredPlaceholders: string[],
378
+ ): Promise<string[]>;
379
+ }
380
+ ```
381
+
382
+ ## Troubleshooting
383
+
384
+ ### Q: Placeholder not replaced?
385
+
386
+ Check for typos in template:
387
+
388
+ ```handlebars
389
+ {{naem}}
390
+ ← Wrong
391
+ {{name}}
392
+ ← Correct
393
+ ```
394
+
395
+ ### Q: Loop not working?
396
+
397
+ Ensure data is an array:
398
+
399
+ ```typescript
400
+ // ❌ Won't iterate
401
+ items: "not an array";
402
+
403
+ // ✅ Will iterate
404
+ items: [{ name: "A" }, { name: "B" }];
405
+ ```
406
+
407
+ ### Q: Image not displaying?
408
+
409
+ Use correct image syntax:
410
+
411
+ ```handlebars
412
+ {{#image path width height}}
413
+ relative/path/to/image.png
414
+ {{/image}}
415
+ ```
416
+
417
+ ### Q: Conditional not working?
418
+
419
+ Ensure condition is boolean:
420
+
421
+ ```typescript
422
+ // ❌ String
423
+ isPremium: "true";
424
+
425
+ // ✅ Boolean
426
+ isPremium: true;
427
+ ```
71
428
 
72
429
  ## Related Packages
73
430
 
74
- - [@zola_do/document-manipulator](../document-manipulator) — PDF/DOCX merge and conversion, uses similar template population
431
+ - [@zola_do/document-manipulator](../document-manipulator) — PDF/DOCX merge and conversion
75
432
  - [@zola_do/minio](../minio) — Store generated documents
76
433
 
434
+ ## License
435
+
436
+ ISC
437
+
77
438
  ## Community
78
439
 
79
440
  - [Contributing](../../CONTRIBUTING.md)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zola_do/docx",
3
- "version": "0.2.5",
3
+ "version": "0.2.7",
4
4
  "description": "DOCX template processing for NestJS",
5
5
  "author": "zolaDO",
6
6
  "license": "ISC",