### Install Docxtemplater and PizZip Source: https://docxtemplater.com/docs/get-started-node Install the necessary libraries for document generation. PizZip is required for handling DOCX/PPTX/XLSX files as zipped archives. ```bash npm install --save docxtemplater pizzip ``` -------------------------------- ### Provide Data for Custom Delimiter Example Source: https://docxtemplater.com/docs/tag-types Data structure to be used with the custom delimiter template example. ```json { "first_name": "John", "last_name": "Doe" } ``` -------------------------------- ### Check Node.js and npm Versions Source: https://docxtemplater.com/docs/get-started-node Verify that Node.js and npm are installed correctly by checking their versions. Ensure you have a compatible version installed. ```bash node --version ``` ```bash npm --version ``` -------------------------------- ### Dash Syntax Loop Data Example Source: https://docxtemplater.com/docs/tag-types Example data structure for use with the dash syntax loop. ```json { "users": [{ "name": "John" }, { "name": "Mary" }] } ``` -------------------------------- ### Data for Root Scope Example Source: https://docxtemplater.com/docs/deep-dive-into-the-parser-option Example data structure to demonstrate accessing a root-level property within loops. ```javascript doc.render({ company: "ACME Company", contractors: [ { company: "The other Company" }, { company: "Foobar Company" }, ], }); ``` -------------------------------- ### Migrate from setData to render Source: https://docxtemplater.com/docs/api This example demonstrates migrating code that uses setData and render to the new constructor and render method. It shows how options and modules are now passed during instantiation. ```javascript const fs = require("fs"); const expressionParser = require("docxtemplater/expressions.js"); const data = { first_name: "John", last_name: "Doe" }; const content = fs.readFileSync("input.docx").toString(); const zip = new PizZip(content); const htmlModule = new HTMLModule(); const doc = new Docxtemplater() .attachModule(htmlModule) .loadZip(zip) .setOptions({ parser: expressionParser, linebreaks: true, paragraphLoop: true, }); doc.compile(); doc.setData(data); doc.render(); const buffer = doc.getZip().generate({ type: "nodebuffer" }); fs.writeFileSync("output.docx", buffer); ``` ```javascript const fs = require("fs"); const expressionParser = require("docxtemplater/expressions.js"); const data = { first_name: "John", last_name: "Doe" }; const content = fs.readFileSync("input.docx").toString(); const zip = new PizZip(content); const htmlModule = new HTMLModule(); const doc = new Docxtemplater(zip, { parser: expressionParser, linebreaks: true, paragraphLoop: true, modules: [htmlModule], }); doc.render(data); const buffer = doc.toBuffer(); fs.writeFileSync("output.docx", buffer); ``` -------------------------------- ### Conditional Rendering Example Source: https://docxtemplater.com/docs/tag-types Conditionally include or exclude content based on boolean values in the data. Use {#condition} to start and {/condition} to end the block. ```docx {#hasKitty}Cat’s name: {kitty}{/hasKitty} {#hasDog}Dog’s name: {dog}{/hasDog} ``` -------------------------------- ### Install angular-expressions Source: https://docxtemplater.com/docs/angular-parse Install the angular-expressions library using npm. Ensure you use version 1.4.3 or higher to avoid security vulnerabilities. ```bash npm install --save angular-expressions ``` -------------------------------- ### Basic Placeholder Tag Example Source: https://docxtemplater.com/docs/tag-types Used to insert data values directly into the template. Ensure the data object contains the key corresponding to the tag. ```docx Hello {name} ! ``` -------------------------------- ### Looping Over Array of Primitives Example Source: https://docxtemplater.com/docs/tag-types Iterate over an array of primitive values (like strings). The '.' symbol refers to the current item in the array. ```docx {#products}{.} {/products} ``` -------------------------------- ### Migrate from resolveData to renderAsync Source: https://docxtemplater.com/docs/api This example shows how to migrate code using the deprecated resolveData method to the new renderAsync method. It also demonstrates changes in constructor usage and module attachment. ```javascript const fs = require("fs"); const expressionParser = require("docxtemplater/expressions.js"); const data = { first_name: "John", last_name: "Doe" }; const content = fs.readFileSync("input.docx").toString(); const zip = new PizZip(content); const htmlModule = new HTMLModule(); const doc = new Docxtemplater() .attachModule(htmlModule) .loadZip(zip) .setOptions({ parser: expressionParser, linebreaks: true, paragraphLoop: true, }); doc.compile(); await doc.resolveData(data); doc.render(); const buffer = doc.getZip().generate({ type: "nodebuffer" }); fs.writeFileSync("output.docx", buffer); ``` ```javascript const fs = require("fs"); const expressionParser = require("docxtemplater/expressions.js"); const data = { first_name: "John", last_name: "Doe" }; const content = fs.readFileSync("input.docx").toString(); const zip = new PizZip(content); const htmlModule = new HTMLModule(); const doc = new Docxtemplater(zip, { parser: expressionParser, linebreaks: true, paragraphLoop: true, modules: [htmlModule], }); await doc.renderAsync(data); const buffer = doc.toBuffer(); fs.writeFileSync("output.docx", buffer); ``` -------------------------------- ### Looping Over Array of Objects Data Example Source: https://docxtemplater.com/docs/tag-types Data for looping over an array of objects. Each object in the array will be processed by the loop. ```json { "products": [ { "name": "Windows", "price": 100 }, { "name": "Mac OSX", "price": 200 }, { "name": "Ubuntu", "price": 0 } ] } ``` -------------------------------- ### Async Rendering with Promises Source: https://docxtemplater.com/docs/async Render your template asynchronously by providing Promises for data. This example resolves user data after a delay, simulating an asynchronous data fetch. ```javascript const path = require("path"); // Compile your document const doc = new Docxtemplater(zip, { paragraphLoop: true, linebreaks: true, }); doc.renderAsync({ user: new Promise((resolve) => { /* * You could also resolve your data from an HTTP request, * an async call to your database, * a call to an external API, ... */ setTimeout(() => resolve("John"), 1000); }), }).then(() => { const buf = doc.toBuffer(); fs.writeFileSync( path.resolve(__dirname, "output.docx"), buf ); }); ``` -------------------------------- ### Looping Over Array of Primitives Data Example Source: https://docxtemplater.com/docs/tag-types Data for looping over an array of primitive values. Each value in the array will be processed by the loop. ```json { "products": ["Windows", "Mac OSX", "Ubuntu"] } ``` -------------------------------- ### Attach Multiple Modules Sequentially (Deprecated) Source: https://docxtemplater.com/docs/api Deprecated method for attaching modules. Use the constructor with options for module configuration. This example shows attaching HTML and Xlsx modules. ```javascript doc.loadZip(zip) .attachModule(new HTMLModule()) .attachModule(new XlsxModule()); ``` -------------------------------- ### Jexl expression example Source: https://docxtemplater.com/docs/angular-parse This is an example of a Jexl expression used within a Docxtemplater template, demonstrating filtering and accessing properties of an array of objects. ```plaintext {employees[.last == 'Tu' + 'nt'].first} ``` -------------------------------- ### Placeholder Tag Data Example Source: https://docxtemplater.com/docs/tag-types The data object used to populate placeholder tags. The keys in the data object should match the tag names in the template. ```json { "name": "John" } ``` -------------------------------- ### Conditional Rendering Data Example Source: https://docxtemplater.com/docs/tag-types Data for conditional rendering. The boolean values determine whether the corresponding sections are rendered. ```json { "hasKitty": true, "kitty": "Minie", "hasDog": false, "dog": null } ``` -------------------------------- ### Get Filetype Not Handled Error ID Source: https://docxtemplater.com/docs/errors This error occurs when a recognized file type (e.g., xlsx, odt) is not supported by the installed modules. Ensure you have the correct paid module for the file type. ```javascript error.id = "filetype_not_handled" error.explanation = `The file you are trying to generate is of type "${fileType}", but only docx and pptx formats are handled` ``` -------------------------------- ### Set Data for Rendering (Deprecated) Source: https://docxtemplater.com/docs/api Deprecated method for setting data. Use `doc.render(tags)` instead. This example shows the expected data object format. ```javascript { "firstName": "David" } ``` -------------------------------- ### Docxtemplater Template Syntax Examples Source: https://docxtemplater.com/docs/configuration Illustrates correct and incorrect usage of loop tags in Docxtemplater templates. Pay attention to whitespace, multiple loops on a line, and the placement of opening and closing tags in separate paragraphs. ```plaintext {#users} foo bar {/} ``` ```plaintext {#loop1}{#loop2} content {/} {/} ``` ```plaintext {#loop1} {#loop2} content {/} {/} ``` ```plaintext {#loop1} {#loop2} content{/}{/} ``` ```plaintext {#loop1} {#loop2} content {/} {/} ``` -------------------------------- ### Looping Over Array of Objects Source: https://docxtemplater.com/docs/tag-types Iterate over an array of objects to repeat a section of the template for each item. Use {#array_name} to start and {/array_name} to end the loop. ```docx {#products} {name}, {price} € {/products} ``` -------------------------------- ### Scope and Context for Default Parser Source: https://docxtemplater.com/docs/deep-dive-into-the-parser-option Illustrates the `scope` and `context` objects passed to the `get` function of the default parser. Understanding these arguments is crucial for debugging and implementing custom parsing logic. ```javascript const scope = { name: "Jane" }; const context = { num: 1, // This corresponds to the level of the nesting, // the {#users} tag is level 0, the {.} is level 1 scopeList: [ { users: [ { name: "Jane", }, { name: "Mary", }, ], }, { name: "Jane", }, ], scopePath: ["users"], scopePathItem: [0], /* * Together, scopePath and scopePathItem describe where we * are in the data, in this case, we are in the tag users[0] * (the first user) */ }; ``` -------------------------------- ### Scope Parser Execution Failed Error Properties and Example Source: https://docxtemplater.com/docs/errors This error occurs when a custom scope parser throws an error during execution, often due to invalid data or logic within the parser. The 'explanation' property identifies the tag causing the execution failure. The example shows how to configure a parser with filters and render data that might cause an error. ```javascript error.id = "scopeparser_execution_failed" error.explanation = `The scope parser for the tag "${tag}" failed to execute` ``` ```javascript const expressionParser = require("docxtemplater/expressions.js"); const doc = new Docxtemplater(zip, { paragraphLoop: true, linebreaks: true, parser: expressionParser.configure({ filters: { toFixed(input) { return input.toFixed(); } } }), }); doc.render({ test: false }); ``` -------------------------------- ### Catching and Handling Docxtemplater Errors Source: https://docxtemplater.com/docs/errors This example shows how to use a try-catch block to handle potential errors during Docxtemplater initialization and rendering. It includes logic to extract and display human-readable error messages from multi-errors. ```javascript let doc; try { /* * The line below can throw an error if the template itself is not valid * (sometimes called TemplateError) */ doc = new Docxtemplater(zip, { paragraphLoop: true, linebreaks: true, }); /* * The line below can throw an error if the parser execution fails or the * data resolving fails. */ doc.render(/* data */); } catch (error) { if ( error.properties && error.properties.errors instanceof Array ) { const errorMessages = error.properties.errors .map((error) => error.properties.explanation) .join("\n"); console.log("errorMessages", errorMessages); /* * errorMessages is a humanly readable message looking like this: * 'The tag beginning with "foobar" is unopened' */ } throw error; } ``` -------------------------------- ### Using Filtrex Parser with Docxtemplater Source: https://docxtemplater.com/docs/angular-parse Integrates Filtrex for parsing tags, enabling dot-access operator for nested data. Requires installation of the 'filtrex' package. ```javascript const { compileExpression, useDotAccessOperator, } = require("filtrex"); const doc = new Docxtemplater(zip, { paragraphLoop: true, linebreaks: true, parser: (tag) => { const fn = compileExpression(tag, { customProp: useDotAccessOperator, }); return { get(scope /* , context */) { return fn(scope); }, }; }, }); doc.render({ foo: { bar: 42 }, }); ``` -------------------------------- ### Default Parser Implementation Source: https://docxtemplater.com/docs/configuration Understand the default parser function's structure. It receives the tag and meta information, and returns an object with a `get` method to resolve data. ```javascript const doc = new Docxtemplater(zip, { parser(tag, meta) { /* * In our example above : * - tag is "name" because {name} contains the "name" string. * - if the template was `Hello { foo + bar }`, * the value of the tag variable would * be : " foo + bar " */ console.log(meta.tag); // { type: "placeholder", value: " foo + bar "} return { get(scope, context) { /* * In our example above, scope is `{ "name": "John" }` * because that is the data passed to docxtemplater */ console.log(context); // the context : { num, meta, scopeList, ...} if (tag === ".") { return scope; } // return the property "name" of the scope object. return scope[tag]; }, }; }, }); doc.render(/* data */); ``` -------------------------------- ### Using Jsonata Parser with Docxtemplater Source: https://docxtemplater.com/docs/angular-parse Integrates Jsonata for parsing tags, allowing complex data querying and transformation. Requires installation of the 'jsonata' package. Use renderAsync as Jsonata is asynchronous. ```javascript const jsonata = require("jsonata"); const doc = new Docxtemplater(zip, { paragraphLoop: true, linebreaks: true, parser: (tag) => { const expression = jsonata(tag); return { get(scope /* , context */) { return expression.evaluate(scope); // returns 24 }, }; }, }); // We use renderAsync because jsonata is async doc.renderAsync({ example: [{ value: 4 }, { value: 7 }, { value: 13 }], }); ``` -------------------------------- ### Custom Parser for Scope Management Source: https://docxtemplater.com/docs/deep-dive-into-the-parser-option This example shows how to define a custom parser function to control how docxtemplater retrieves values for tags. It includes logic for handling the '.' tag and accessing properties within scopes. ```javascript const options = { // This is how docxtemplater is configured by default parser(tag, meta) { /* * tag is the string "users", or whatever you have put inside the * brackets, eg if your tag was {a==b}, then the value of tag would be * "a==b" * meta.tag will have the following shape : * { * tag: { * type: 'placeholder', * module: 'loop', * inverted: false, * value: 'users', * offset: 6, * endLindex: 29, * lIndex: 4, * raw: '#users', * sectPrCount: 0, * lastParagrapSectPr: '', * subparsed: [ * [Object], * [Object], * [Object], * [Object], * [Object], * [Object], * [length]: 6 * } */ return { get(scope, context) { /* * When treating the nested property "name" for the first call, the value will be : * The scope will be : * * { name: "John", hobby: "Basketball" }, * * The context variable has following properties : * * { * scopeList: [ { users: [Array] }, { name: "John", hobby: "Basketball" }], * resolved: undefined, * scopePath: [ 'users'], * scopeTypes: [ 'array'], * scopePathItem: [ 0], * scopePathLength: [ 2] * } */ if (tag === ".") { return scope; } // Here we return the property "users" of the object {users: [....]} return scope[tag]; }, }; }, }; const doc = new Docxtemplater(zip, options); doc.render(/* data */); ``` -------------------------------- ### Configure postCompile for assignment resolution Source: https://docxtemplater.com/docs/angular-parse The `postCompile` option allows you to modify tag compilation behavior. This example ensures assignment expressions are resolved first by setting `meta.tag.resolveFirst = true`. ```javascript const expressionParser = require("docxtemplater/expressions.js"); const doc = new Docxtemplater(zip, { parser: expressionParser.configure({ postCompile(tag, meta, expr) { const lastBody = expr.ast.body[expr.ast.body.length - 1]; const isAssignment = lastBody && lastBody.expression.type === "AssignmentExpression"; if (isAssignment) { meta.tag.resolveFirst = true; } }, }), }); doc.render(/* data */); ``` -------------------------------- ### Conditional rendering with Angular parser Source: https://docxtemplater.com/docs/angular-parse Utilize conditional expressions within your templates for dynamic content rendering. This example demonstrates checking array length and specific element properties. ```html {#users.length > 1} There are multiple users {/} {#users[0].name == "John"} Hello {users[0].name}, welcome back {/} ``` -------------------------------- ### Complex conditional logic with operators Source: https://docxtemplater.com/docs/angular-parse Implement advanced conditional logic using various operators like equality, relational, logical AND/OR, and ternaries. This example showcases multiple conditions and assignments. ```html {#myType === "users"} There are {users.length} users. {#cond1 || cond2} Paragraph 1 {/} {#cond2 && cond3} Paragraph 2 {/} {#cond4 ? users : usersWithAdminRights} Paragraph 3 {/} {/} ``` -------------------------------- ### Docxtemplater Error Logging JSON Example Source: https://docxtemplater.com/docs/configuration This JSON output shows the structure of a template error when errorLogging is set to 'json'. It includes error details like name, message, stack trace, and specific properties related to the error. ```json { "error": [ { "name": "TemplateError", "message": "Closing tag does not match opening tag", "stack": "Error: Closing tag does not match opening tag\n at new XTTemplateError (/home/edgar/www/xt/es6/errors.js:13:15)\n at getClosingTagNotMatchOpeningTag (/home/edgar/www/xt/es6/errors.js:260:14)\n at transformer (/home/edgar/www/xt/es6/modules/expand-pair-trait.js:71:5)\n at getPairs (/home/edgar/www/xt/es6/modules/expand-pair-trait.js:102:18)\n at ExpandPairTrait.postparse (/home/edgar/www/xt/es6/modules/expand-pair-trait.js:152:29)\n at postparse (/home/edgar/www/xt/es6/parser.js:175:36)\n at Object.postparse (/home/edgar/www/xt/es6/parser.js:193:24)\n at XmlTemplater.postparse (/home/edgar/www/xt/es6/xml-templater.js:126:59)\n at Docxtemplater.compile (/home/edgar/www/xt/es6/docxtemplater.js:570:29)\n at new Docxtemplater (/home/edgar/www/xt/es6/docxtemplater.js:270:9)\n at makeDocxV4 (/home/edgar/www/xt/es6/tests/utils.js:861:9)\n at /home/edgar/www/xt/es6/tests/e2e/errors.js:156:5 at expectToThrow (/home/edgar/www/xt/es6/tests/utils.js:470:3) at Context. (/home/edgar/www/xt/es6/tests/e2e/errors.js:154:3) at callFn (/home/edgar/www/xt/node_modules/mocha/lib/runnable.js:364:21) at Runnable.run (/home/edgar/www/xt/node_modules/mocha/lib/runnable.js:352:5) at Runner.runTest (/home/edgar/www/xt/node_modules/mocha/lib/runner.js:677:10) at /home/edgar/www/xt/node_modules/mocha/lib/runner.js:800:12 at next (/home/edgar/www/xt/node_modules/mocha/lib/runner.js:592:14) at /home/edgar/www/xt/node_modules/mocha/lib/runner.js:602:7 at next (/home/edgar/www/xt/node_modules/mocha/lib/runner.js:485:14) at Immediate._onImmediate (/home/edgar/www/xt/node_modules/mocha/lib/runner.js:570:5) at process.processImmediate (node:internal/timers:483:21)", "properties": { "id": "closing_tag_does_not_match_opening_tag", "explanation": "The tag \"users\" is closed by the tag \"foo\"", "openingtag": "users", "offset": [ 0, 19 ], "closingtag": "foo", "file": "word/document.xml" } } ] } ``` -------------------------------- ### Creating Table Rows with Loops in Docxtemplater Source: https://docxtemplater.com/docs/tag-types Use loop tags within table cells to generate multiple rows. The loop start and end tags should span the cells of a single row. ```docx Name| Age| Phone Number ---|---|--- {#users}{name}| {age}| {phone}{/} ``` ```json { "users": [ { "name": "John", "age": 22, "phone": "+33777777777" }, { "name": "Mary", "age": 25, "phone": "+33666666666" } ] } ``` -------------------------------- ### Custom Parser for Lowercase and Uppercase Tags Source: https://docxtemplater.com/docs/deep-dive-into-the-parser-option Implement a custom parser to handle tags with \`[lower]\` or \`[upper]\` suffixes for case conversion. This example transforms tags like \`{user[lower]}\` to \`{user}\` and applies the specified case to the retrieved data. ```javascript const options = { parser(tag) { // tag can be "user[lower]", "user", or "user[upper]" const lowerRegex = /\\[lower\\]$/; const upperRegex = /\\[upper\\]$/; let changeCase = ""; if (lowerRegex.test(tag)) { changeCase = "lower"; // transform tag from "user[lower]" to "user" tag = tag.replace(lowerRegex, ""); } if (upperRegex.test(tag)) { changeCase = "upper"; // transform tag from "user[upper]" to "user" tag = tag.replace(upperRegex, ""); } return { get(scope) { let result = null; // scope will be {user: "John"} if (tag === ".") { result = scope; } else { // Here we use the property "user" of the object {user: "John"} result = scope[tag]; } if (typeof result === "string") { if (changeCase === "upper") { return result.toUpperCase(); } else if (changeCase === "lower") { return result.toLowerCase(); } } return result; }, }; }, paragraphLoop: true, linebreaks: true, }; new Docxtemplater(zip, options); ``` -------------------------------- ### Initializing Docxtemplater Instance Source: https://docxtemplater.com/docs/deep-dive-into-docxtemplater-internals This code shows the final step of initializing the Docxtemplater instance with a zip file object and options. This is the entry point for compiling and rendering a document. ```javascript /* eslint-disable-next-line no-unused-vars, no-undef */ const doc = new Docxtemplater(zip, options); ``` -------------------------------- ### Docx-Templater Compilation and Rendering Steps Source: https://docxtemplater.com/docs/deep-dive-into-docxtemplater-internals Demonstrates the two main steps in using Docx-Templater: compilation and rendering. Compilation checks the template for errors, while rendering populates placeholders with data. ```javascript /* * Step1 : compilation (only takes the zip file as an argument and will check * the template for errors, such as if the template misses a closing tag, for * example, with the following template : * * ```docx * Hello {name * ``` * * An error will be thrown to tell that there is an unclosed tag. * * For a valid document, such as : * * ```docx * Hi {user} * ``` * * It will return a valid compiled document. */ const doc = new Docxtemplater(zip, { paragraphLoop: true, linebreaks: true, }); /* * Step2 : rendering (add data to a compiled document) * This takes a compiled document and fills in all placeholders. */ doc.render({ description: "New Website", }); ``` -------------------------------- ### new Docxtemplater(zip, options) Source: https://docxtemplater.com/docs/api Creates a new Docxtemplater instance. This is the preferred constructor for initializing the library with a zip file and configuration options. ```APIDOC ## Constructor: new Docxtemplater(zip, options) ### Description Initializes a new Docxtemplater instance with a zip file and optional configuration. ### Parameters * **zip** (object) - Required - A zip instance (from pizzip or jszip v2) representing the document. * **options** (object) - Optional - Configuration options for delimiters, modules, etc. * **modules** (array) - Optional - List of modules to attach (e.g., HTMLModule). * **delimiters** (object) - Optional - Custom delimiters for template tags. * **start** (string) - The starting delimiter. * **end** (string) - The ending delimiter. ### Request Example ```javascript const options = { modules: [new HTMLModule()], delimiters: { start: "<", end: ">", } }; const doc = new Docxtemplater(zip, options); ``` ``` -------------------------------- ### Basic Docxtemplater Initialization Source: https://docxtemplater.com/docs/configuration Initialize Docxtemplater with an options object. This is the standard way to configure the library. ```javascript const options = { paragraphLoop: true, linebreaks: true }; const doc = new Docxtemplater(zip, options); doc.render(/* data */); ``` -------------------------------- ### Create Docxtemplater Instance with Options Source: https://docxtemplater.com/docs/api Instantiate Docxtemplater with custom modules. Ensure the HTMLModule is imported if used. ```javascript const options = { modules: [new HTMLModule()], }; const doc = new Docxtemplater(zip, options); doc.render(/* data */); ``` -------------------------------- ### Run the Document Generation Script Source: https://docxtemplater.com/docs/get-started-node Execute the Node.js script to process the template and create the output document. This command should be run from the directory containing your script and template. ```bash node your_script_name.js ``` -------------------------------- ### Initialize and Render with Error Handling Source: https://docxtemplater.com/docs/errors This snippet demonstrates initializing Docxtemplater and rendering content, showing where TemplateError and RenderingError can occur. It's useful for basic error detection during template processing. ```javascript // The line below can throw an error if the template itself is not valid (sometimes called TemplateError) const doc = new Docxtemplater(zip, { paragraphLoop: true, linebreaks: true, }); // The line below can throw an error if the parser execution fails or the data resolving fails. (sometimes called RenderingError) doc.renderAsync({ first_name: "John", last_name: "Doe", phone: "0652455478", description: "New Website", }); ``` -------------------------------- ### Get Unclosed Tag Error ID Source: https://docxtemplater.com/docs/errors This error signifies an opening tag was not closed in the template. Ensure all opened tags are properly closed. ```javascript error.id = "unclosed_tag" error.explanation = `The tag beginning with "${options.xtag.substr(0, 30)}" is unclosed` ``` -------------------------------- ### Reconstructing ImageModule Instance (Correct) Source: https://docxtemplater.com/docs/errors This code shows the correct way to use ImageModule by reconstructing an instance for each Docxtemplater instance, preventing errors. ```javascript const Docxtemplater = require("docxtemplater"); const ImageModule = require("docxtemplater-image-module"); const imageOptions = { getImage(tagValue, tagName, meta) { console.log({ tagValue, tagName, meta }); return fs.readFileSync(tagValue); }, getSize() { // it also is possible to return a size in centimeters, like this : return [ "2cm", "3cm" ]; return [150, 150]; }, }; function generate(content) { const zip = new PizZip(content); const imageModule = new ImageModule(imageOptions); const doc = new Docxtemplater(zip, { paragraphLoop: true, linebreaks: true, modules: [imageModule], }); doc.render(data); } generate(); generate(); ``` -------------------------------- ### Async Rendering with Async/Await Source: https://docxtemplater.com/docs/async Utilize the async/await syntax for a cleaner approach to asynchronous template rendering. This snippet shows the basic structure for awaiting the render operation. ```javascript await doc.renderAsync(/* data */); doc.toBuffer(); ``` -------------------------------- ### Get API Version Error ID Source: https://docxtemplater.com/docs/errors This error occurs when a module version requires a newer Docxtemplater core API version. Update Docxtemplater to resolve. ```javascript error.id = "api_version_error" ``` -------------------------------- ### Custom Assignment Scope with setIdentifier Source: https://docxtemplater.com/docs/angular-parse Customize assignment scope handling by providing a custom `setIdentifier` function to the expression parser. This example assigns the variable to the root scope. ```javascript const expressionParser = require("docxtemplater/expressions.js"); new Docxtemplater(zip, { paragraphLoop: true, linebreaks: true, parser: expressionParser.configure({ setIdentifier(tag, value, currentScope, scopeList) { /* * In our context scopeList[0] is the same as `data` * * - scopeList[1] will be the child scope (if it exists) * => will be { name: "John" } for the first iteration * - scopeList[2] will be the child child scope (if it exists) * => in your case there is just one level loop * - currentScope will in our case be the same as scopeList[1] */ const rootScope = scopeList[0]; rootScope[tag] = value; // return true to notify to the expressionParser that we handled this assignment return true; }, }), }); ``` -------------------------------- ### Lexing with Delimiters: Identifying Placeholders Source: https://docxtemplater.com/docs/deep-dive-into-docxtemplater-internals This step shows the lexing process after delimiters (like '{' and '}') have been parsed, assigning a specific 'delimiter' type to them. This prepares for placeholder identification. ```javascript /* eslint-disable-next-line no-unused-vars */ const lexed = [ { type: "tag", position: "start", value: "", text: true, tag: "w:t", }, { type: "content", value: "Hi ", position: "insidetag" }, { type: "delimiter", position: "start" }, { type: "content", value: "user", position: "insidetag" }, { type: "delimiter", position: "end" }, { type: "tag", value: "", text: true, position: "end", tag: "w:t", }, ]; ``` -------------------------------- ### Basic HTML Page with Docxtemplater Source: https://docxtemplater.com/docs/get-started-browser This HTML structure includes Docxtemplater, PizZip, and FileSaver scripts, along with a JavaScript function to generate a document when a button is clicked. It demonstrates loading a template, rendering it with data, and saving the output. ```html ``` -------------------------------- ### Nested property access with Angular parser Source: https://docxtemplater.com/docs/angular-parse Use dot notation for accessing nested properties after setting up the Angular parser. This example shows accessing `user.name` from nested data. ```javascript const expressionParser = require("docxtemplater/expressions.js"); const parser = expressionParser.configure({}); const doc = new Docxtemplater(zip, { parser, }); doc.render({ user: { name: "John", }, }); ``` -------------------------------- ### Get Duplicate Close Tag Error ID Source: https://docxtemplater.com/docs/errors This error occurs when a tag has duplicate closing tags in the template. Ensure each opening tag has only one corresponding closing tag. ```javascript error.id = "duplicate_close_tag" error.explanation = `The tag ending with "${options.xtag.substr(0, 30)}" has duplicate close tags` ``` -------------------------------- ### Get Unopened Tag Error ID Source: https://docxtemplater.com/docs/errors This error indicates a closing tag was found without a corresponding opening tag in the template. Ensure all tags are properly opened before being closed. ```javascript error.id = "unopened_tag" error.explanation = `The tag beginning with "${options.xtag.substr(0, 30)}" is unopened` ``` -------------------------------- ### Generate Document with Node.js Source: https://docxtemplater.com/docs/get-started-node This script reads a DOCX template, replaces placeholders with provided data, and saves the generated document. Ensure 'input.docx' exists in the same directory. ```javascript // Load our library that generates the document const Docxtemplater = require("docxtemplater"); // Load PizZip library to load the docx/pptx/xlsx file in memory const PizZip = require("pizzip"); // Builtin file system utilities const fs = require("fs"); const path = require("path"); // Load the docx file as binary content const content = fs.readFileSync( path.resolve(__dirname, "input.docx"), "binary" ); // Unzip the content of the file const zip = new PizZip(content); /* * Parse the template. * This function throws an error if the template is invalid, * for example, if the template is "Hello {user" (missing closing tag) */ const doc = new Docxtemplater(zip, { paragraphLoop: true, linebreaks: true, }); /* * Render the document : Replaces : * - {first_name} with John * - {last_name} with Doe, * ... */ doc.render({ first_name: "John", last_name: "Doe", phone: "+33666666", description: "The Acme Product", }); /* * Get the output document and export it as a Node.js buffer * This method is available since docxtemplater@3.62.0 */ const buf = doc.toBuffer(); // Write the Buffer to a file fs.writeFileSync(path.resolve(__dirname, "output.docx"), buf); /* * Instead of writing it to a file, you could also * let the user download it, store it in a database, * on AWS S3, ... */ ``` -------------------------------- ### Render Data with $index Access Source: https://docxtemplater.com/docs/angular-parse Provides sample data for rendering with expressions that utilize the `$index` variable to access elements from multiple arrays simultaneously. ```javascript doc.render({ names: ["John", "Mary"], ages: [15, 26], }); ``` -------------------------------- ### Get No XML Tag Found at Right Error ID Source: https://docxtemplater.com/docs/errors This error occurs when a rawXMLTag cannot access the required XML element on the right. Ensure the necessary adjacent XML tags are present. ```javascript error.id = "no_xml_tag_found_at_right" error.explanation = `No tag "${options.element}" was found at the right` ``` -------------------------------- ### Render Compiled Template with Data Source: https://docxtemplater.com/docs/deep-dive-into-docxtemplater-internals Iterates through parts and modules to render content. Returns the rendered module output if successful. ```javascript /* eslint-disable no-undef */ const parts = [ { type: "tag", position: "start", value: '', text: true, tag: "w:t", }, { type: "content", value: "Hi ", position: "insidetag" }, { type: "placeholder", value: "user" }, { type: "tag", value: "", text: true, position: "end", tag: "w:t", }, ]; const options = { filePath: "word/document.xml", }; for (const part of parts) { for (mod of modules) { const moduleRendered = mod.render(part, options); if (moduleRendered) { return moduleRendered; } } } ``` -------------------------------- ### Render HTML with newlines using postEvaluate Source: https://docxtemplater.com/docs/angular-parse Use the `postEvaluate` option to transform results before rendering. This example replaces newline characters with HTML `
` tags for proper display in HTML contexts. ```javascript const expressionParser = require("docxtemplater/expressions.js"); const htmlModuleNameBlock = "pro-xml-templating/html-module-block"; const htmlModuleNameInline = "pro-xml-templating/html-module-inline"; const htmlPptxModuleNameBlock = "pro-xml-templating/html-pptx-module-block"; const htmlPptxModuleNameShape = "pro-xml-templating/html-pptx-module-shape"; const htmlPptxModuleNameInline = "pro-xml-templating/html-pptx-module-inline"; const htmlModuleTags = [ htmlModuleNameBlock, htmlModuleNameInline, htmlPptxModuleNameBlock, htmlPptxModuleNameShape, htmlPptxModuleNameInline, ]; const doc = new Docxtemplater(zip, { paragraphLoop: true, linebreaks: true, parser: expressionParser.configure({ postEvaluate(result, tag, scope, context) { if ( htmlModuleTags.indexOf( context.meta.part.module ) !== -1 && typeof result === "string" ) { // for all html tags, replace "\n" by "
" result = result.replace(/\n/g, "
"); } return result; }, }), modules: [new HTMLModule(), new HTMLPptxModule()], }); doc.render({ htmlDescription: "Dear Edgar,\nWhat's your plan today ?", }); ``` -------------------------------- ### Dash Syntax for Paragraph Loops Source: https://docxtemplater.com/docs/tag-types Use `{-w:p loop}` to create a new paragraph for each item in a loop, providing more control than standard loops. ```docx {-w:p users}{name}{/} ``` -------------------------------- ### DOCX File Structure Overview Source: https://docxtemplater.com/docs/deep-dive-into-docxtemplater-internals Illustrates the hierarchical structure of a DOCX file, which is a zipped collection of XML files. Key directories include docProps, word, and _rels. ```treeview +--docProps | + app.xml // Contains the name of the software used for ] | | // creating the document, the number of pages, characters, | | // and some other configuration | \ core.xml // Contains the name of the creator of the document, | // the revision, and the last modification date. +--word | // This folder contains most of the files | // that control the content of the document | | + document.xml // Contains the main content of the document. | + endnotes.xml | + fontTable.xml | + footer1.xml // Contains the content of the footer of the document | | // (there can be multiple footers called footer1.xml, footer2.xml, ...) | + footnotes.xml | +--media // This folder contains all images embedded in the word document | | \ image1.jpeg | + settings.xml | + styles.xml | + stylesWithEffects.xml | +--theme | | \ theme1.xml | + webSettings.xml | \--_rels | \ document.xml.rels // This document tells where each image is located, | // and all Relationships + [Content_Types].xml \--_rels \ .rels ``` -------------------------------- ### Browser Integration with File Input Source: https://docxtemplater.com/docs/get-started-browser This HTML code sets up a file input and a button to generate a document using Docxtemplater. It includes necessary CDN links for Docxtemplater, PizZip, and FileSaver.js. The script handles file reading, template rendering, and saving the output DOCX file. ```html ``` -------------------------------- ### Get Filetype Not Identified Error ID Source: https://docxtemplater.com/docs/errors Triggered when a zip file is not recognized as a supported document type (docx, pptx, odt). Ensure the file is a valid document or has the necessary paid module. ```javascript error.id = "filetype_not_identified" error.explanation = `The filetype for this file could not be identified, is this file corrupted ? ${msg}` ``` -------------------------------- ### Get No XML Tag Found at Left Error ID Source: https://docxtemplater.com/docs/errors This error arises when a rawXMLTag attempts to expand to adjacent XML tags but cannot access the required element on the left, such as a missing `` tag. ```javascript error.id = "no_xml_tag_found_at_left" error.explanation = `No tag "${options.element}" was found at the left` ```