### Configuration Guide Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/INDEX.md A guide on how to configure the library, covering plugin setup, tag processing options, delimiters, and custom data resolvers. ```APIDOC ## Configuration Guide ### Description Instructions and examples for configuring `easy-template-x` to suit specific needs. ### Key Configuration Areas - Plugin setup and management. - Tag processing options, including skipping empty tags. - Customizing tag delimiters. - Configuring the maximum XML nesting depth. - Setting up and using extension hooks. - Implementing custom data resolvers for dynamic data retrieval. ### Examples Complete configuration examples demonstrating various scenarios. ``` -------------------------------- ### Full Office Document Usage Example Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/api-reference/Office.md This example demonstrates loading a DOCX file, accessing its main document, querying XML elements, retrieving text content, managing relationships, saving changes, and exporting the modified document. Ensure you have the 'easy-template-x' library installed and a 'template.docx' file in your project. ```typescript import * as fs from 'fs'; import { Docx, RelType, OmlNode } from 'easy-template-x'; import { xml } from 'easy-template-x'; const templateFile = fs.readFileSync('template.docx'); const docx = await Docx.load(templateFile); // Access main document const mainDoc = docx.mainDocument; // Get XML root const xmlRoot = await mainDoc.xmlRoot(); // Find all paragraphs const paragraphs = xml.query.descendants( xmlRoot, 20, node => xml.query.isGeneralNode(node) && node.nodeName === OmlNode.W.Paragraph ); console.log('Found', paragraphs.length, 'paragraphs'); // Get document text const text = await mainDoc.getText(); console.log('Text:', text); // Get relationships const rels = await mainDoc.rels.list(); console.log('Relationships:', rels.length); // Save changes await mainDoc.save(); // Export result const result = await docx.export(); fs.writeFileSync('output.docx', result); ``` -------------------------------- ### Chart Data Usage Example Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/api-reference/Constants.md Example demonstrating how to import and use DateTimeFormatValues to set the format code for chart categories. Ensure the 'easy-template-x' library is installed. ```typescript import { DateTimeFormatValues } from 'easy-template-x'; const data = { chart: { _type: 'chart', categories: { names: [new Date(2024,0,1), new Date(2024,1,1)], formatCode: DateTimeFormatValues.Date_DayMonthYear // 'd-mmm-yy' }, series: [{ values: [100, 200] }] } }; ``` -------------------------------- ### LinkPlugin Example Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/api-reference/Plugins.md Example of how to structure data for the LinkPlugin to create a clickable hyperlink with custom text and tooltip. ```typescript const data = { homepage: { _type: 'link', text: 'Visit our website', target: 'https://example.com', tooltip: 'Official website' } }; // Template tag: {homepage} becomes clickable link ``` -------------------------------- ### Example ExtensionOptions Configuration Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/api-reference/Extensions.md Demonstrates how to configure the ExtensionOptions interface with specific extension instances for before and after compilation phases. ```typescript const options = { beforeCompilation: [ new PreprocessExtension(), new ValidationExtension() ], afterCompilation: [ new PostprocessExtension() ] }; ``` -------------------------------- ### TextPlugin Example Data Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/api-reference/Plugins.md Example data structure for demonstrating TextPlugin, including single-line and multi-line text values. ```typescript const data = { name: 'John Doe', title: 'Software Engineer', bio: 'A multi-line biography goes here' }; // Tags {name}, {title}, {bio} are all handled by TextPlugin ``` -------------------------------- ### StandardChartData Usage Example Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/types.md Example demonstrating how to structure data for a standard chart, such as a sales chart with revenue and expenses. ```typescript const data = { salesChart: { _type: 'chart', title: '2024 Sales', categories: { names: ['Q1', 'Q2', 'Q3', 'Q4'] }, series: [ { name: 'Revenue', color: '#34d399', values: [100, 210, 150, 170] }, { name: 'Expenses', color: '#f87171', values: [70, 165, 120, 155] } ] } }; ``` -------------------------------- ### ChartPlugin Example: Line Chart Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/api-reference/Plugins.md Example data structure for creating a line chart with multiple series, custom titles, and colors. ```typescript const data = { salesChart: { _type: 'chart', title: '2024 Sales', categories: { names: ['Q1', 'Q2', 'Q3', 'Q4'] }, series: [ { name: 'Revenue', color: '#3b82f6', values: [100, 200, 150, 250] }, { name: 'Expenses', color: '#ef4444', values: [80, 120, 100, 140] } ] } }; ``` -------------------------------- ### Example execute Method Implementation Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/api-reference/Extensions.md An example implementation of the execute method for a template extension. It demonstrates accessing the XML root and modifying it, as well as accessing template data. ```typescript public async execute(data: ScopeData, context: TemplateContext): Promise { const xmlRoot = await context.currentPart.xmlRoot(); // Modify XML using xml utilities // Access template data via data.getScopeData() } ``` -------------------------------- ### LinkContent Usage Example Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/types.md Example of creating a LinkContent object for a GitHub repository link. If 'text' is omitted, the 'target' URL will be used as the display text. ```typescript const data = { github: { _type: 'link', text: 'View on GitHub', target: 'https://github.com/alonrbar/easy-template-x', tooltip: 'Easy Template X Repository' } }; ``` -------------------------------- ### ImageContent Usage Example Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/types.md Example of how to construct an ImageContent object for embedding a logo. Ensure 'source' is a binary representation of the image file. ```typescript const data = { logo: { _type: 'image', source: fs.readFileSync('logo.png'), format: MimeType.Png, width: 200, height: 100, altText: 'Company Logo' } }; ``` -------------------------------- ### RawXmlPlugin Example: Multiple XML Elements Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/api-reference/Plugins.md Example of using RawXmlPlugin to insert multiple XML elements, such as defining a new section and adding text. ```typescript const data = { section: { _type: 'rawXml', xml: [ '...', 'New section' ] } }; ``` -------------------------------- ### Example: Custom Delimiters Configuration Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/types.md Demonstrates how to instantiate a TemplateHandler with custom delimiters. This allows for a different syntax for simple tags and container tags. ```typescript const handler = new TemplateHandler({ delimiters: { tagStart: '{{', tagEnd: '}}', containerTagOpen: '>>', containerTagClose: '<<' } }); // Now use: {{tagName}} for simple tags and {{>>loop}}...{{<<}} for loops ``` -------------------------------- ### Simple Condition Example Source: https://github.com/alonrbar/easy-template-x/blob/master/README.md Render content conditionally based on a boolean value using loop syntax. This example shows two lines rendered based on different truthy values. ```javascript { lines: [ { visible: true }, { invisible: true } ] } ``` -------------------------------- ### Counter Plugin Example Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/api-reference/Plugins.md A `TemplatePlugin` that increments a counter. It reads `start` and `step` values from scope data and replaces the tag's text content with the calculated result. ```typescript export class CounterPlugin extends TemplatePlugin { public readonly contentType = 'counter'; public simpleTagReplacements(tag: Tag, data: ScopeData): void { const value = data.getScopeData(); if (!value) return; const count = value.start || 0; const increment = value.step || 1; const result = count + increment; // Replace tag with result const textNode = (tag as any).xmlTextNode; textNode.textContent = result.toString(); } } interface CounterContent { _type: 'counter'; start?: number; step?: number; } ``` -------------------------------- ### Integrating Custom Plugins Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/README.md Extend Easy-Template-X functionality by creating and adding custom plugins. This example defines a simple plugin and includes it with default plugins. ```typescript class CustomPlugin extends TemplatePlugin { public readonly contentType = 'custom'; public simpleTagReplacements(tag, data, context): void { // Custom logic } } const handler = new TemplateHandler({ plugins: [ ...createDefaultPlugins(), new CustomPlugin() ] }); ``` -------------------------------- ### Text Plugin Example Source: https://github.com/alonrbar/easy-template-x/blob/master/README.md Use the Text plugin for simple tag replacement in templates. It preserves the original text style. ```json { "First Tag": "Quis et ducimus voluptatum\nipsam id.", "Second Tag": "Dolorem sit voluptas magni dolorem molestias." } ``` -------------------------------- ### Quick Start: Generate DOCX from Template Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/README.md This snippet demonstrates the basic workflow for generating a DOCX document. It involves reading a template file, preparing data, processing the template with TemplateHandler, and saving the output. Ensure you have 'fs' and 'easy-template-x' imported. ```typescript import * as fs from 'fs'; import { TemplateHandler } from 'easy-template-x'; // 1. Read template const templateFile = fs.readFileSync('template.docx'); // 2. Prepare data const data = { name: 'John Doe', items: [ { description: 'Item 1', price: 100 }, { description: 'Item 2', price: 200 } ] }; // 3. Process template const handler = new TemplateHandler(); const doc = await handler.process(templateFile, data); // 4. Save output fs.writeFileSync('output.docx', doc); ``` -------------------------------- ### Handle UnknownContentTypeError Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/errors.md Example demonstrating a scenario that throws an UnknownContentTypeError. This occurs when the '_type' property in the data object does not match any configured plugin. ```typescript const data = { myTag: { _type: 'unknownType', // No plugin handles 'unknownType' value: 'test' } }; // Throws: UnknownContentTypeError await handler.process(templateFile, data); ``` -------------------------------- ### Standard Delimiters Example Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/configuration.md Configures the TemplateHandler with standard curly brace delimiters. Useful for basic templating needs. ```typescript const handler = new TemplateHandler({ delimiters: { tagStart: "{", tagEnd: "}", containerTagOpen: "#", containerTagClose: "/" } }); // Usage: {name} {#items}...{/} ``` -------------------------------- ### ChartPlugin Example: Bubble Chart Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/api-reference/Plugins.md Example data structure for a bubble chart, where data points include x, y coordinates and a size property. ```typescript const data = { bubbles: { _type: 'chart', series: [ { name: 'Data', values: [ { x: 1, y: 10, size: 50 }, { x: 3, y: 25, size: 100 } ] } ] } }; ``` -------------------------------- ### Browser Document Generation Source: https://github.com/alonrbar/easy-template-x/blob/master/README.md This example demonstrates how to generate docx documents within a browser environment. It fetches the template file using fetch API and utilizes a helper function to save the generated document. ```typescript import { TemplateHandler } from 'easy-template-x'; // 1. read template file // (in this example we're loading the template by performing // an AJAX call using the fetch API, another common way to // get your hand on a Blob is to use an HTML File Input) const response = await fetch('http://somewhere.com/myTemplate.docx'); const templateFile = await response.blob(); // 2. process the template const data = { posts: [ { author: 'Alon Bar', text: 'Very important\ntext here!' }, { author: 'Alon Bar', text: 'Forgot to mention that...' } ] }; const handler = new TemplateHandler(); const doc = await handler.process(templateFile, data); // 3. save output saveFile('myTemplate - output.docx', doc); function saveFile(filename, blob) { // see: https://stackoverflow.com/questions/19327749/javascript-blob-filename-without-link // get downloadable url from the blob const blobUrl = URL.createObjectURL(blob); // create temp link element let link = document.createElement("a"); link.download = filename; link.href = blobUrl; // use the link to invoke a download document.body.appendChild(link); link.click(); // remove the link setTimeout(() => { link.remove(); window.URL.revokeObjectURL(blobUrl); link = null; }, 0); } ``` -------------------------------- ### LoopPlugin Example: Conditional Rendering Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/api-reference/Plugins.md Shows conditional rendering using LoopPlugin. The content inside {#isPremium} and {/} is rendered only if 'isPremium' is true. ```typescript // Template: {#isPremium}Premium content{/} const data = { isPremium: true }; // Output: "Premium content" ``` -------------------------------- ### ScatterChartData Usage Example Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/types.md Example showing how to structure data for a scatter plot, with series containing multiple x,y coordinate pairs. ```typescript const data = { scatterPlot: { _type: 'chart', series: [ { name: 'Group A', color: '#3b82f6', values: [ { x: 1, y: 310 }, { x: 3, y: 450 }, { x: 6, y: 200 } ] } ] } }; ``` -------------------------------- ### OpenXmlPart Rels Property and Add Relationship Example Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/api-reference/Office.md Provides access to the relationship manager for a part. Demonstrates adding a hyperlink relationship to an external resource. ```typescript public readonly rels: RelsFile // Add a hyperlink relationship const relId = await part.rels.add( 'https://example.com', RelType.Link, 'External' ); ``` -------------------------------- ### Complete TemplateHandlerOptions Configuration Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/api-reference/TemplateHandlerOptions.md Demonstrates a comprehensive setup of TemplateHandlerOptions, including enabling all default plugins, configuring skipEmptyTags, defaultContentType, containerContentType, custom delimiters, maxXmlDepth, and extensions. ```typescript import { TemplateHandler, TemplateHandlerOptions, createDefaultPlugins } from 'easy-template-x'; const options = new TemplateHandlerOptions({ // Use all built-in plugins plugins: createDefaultPlugins(), // Keep empty tags in document if data is missing skipEmptyTags: true, // Default handler for untyped values defaultContentType: 'text', // Handler for loops and conditions containerContentType: 'loop', // Custom delimiters for template syntax delimiters: { tagStart: '{{', tagEnd: '}}', containerTagOpen: 'LOOP:', containerTagClose: 'END' }, // Increase XML depth limit for complex documents maxXmlDepth: 30, // Add custom extensions for document manipulation extensions: { beforeCompilation: [], afterCompilation: [] }, // Use custom scope data resolver for advanced expressions scopeDataResolver: undefined }); const handler = new TemplateHandler(options); ``` -------------------------------- ### Unicode Delimiters Example Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/configuration.md Configures the TemplateHandler using Unicode characters for delimiters. This offers a unique visual style for templates. ```typescript const handler = new TemplateHandler({ delimiters: { tagStart: "«", tagEnd: "»", containerTagOpen: "#", containerTagClose: "/" } }); // Usage: «name» «#items»...«/» ``` -------------------------------- ### Handle InternalError Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/errors.md Illustrates how to catch and handle an InternalError. This example logs a message indicating a potential library bug and suggests reporting it. ```typescript try { const result = await handler.process(templateFile, data); } catch (error) { if (error instanceof InternalError) { console.error('Library bug:', error.message); // Consider reporting as bug } } ``` -------------------------------- ### RawXmlPlugin Example: Page Break Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/api-reference/Plugins.md Example of using RawXmlPlugin to insert a page break into the document. Setting `replaceParagraph` to true ensures the break is inserted correctly. ```typescript const data = { pageBreak: { _type: 'rawXml', xml: '', replaceParagraph: true } }; // Template tag: {pageBreak} inserts page break ``` -------------------------------- ### ImagePlugin Example: Placeholder Replacement Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/api-reference/Plugins.md Shows how to replace a placeholder image in a template using ImagePlugin. The plugin preserves the placeholder's size and position. 'width' and 'height' are optional in this mode. ```typescript // Template contains placeholder image with alt text: {productImage} const data = { productImage: { _type: 'image', source: fs.readFileSync('product.jpg'), format: 'image/jpeg', transparencyPercent: 20 } }; // Plugin replaces placeholder, preserves size/position ``` -------------------------------- ### LoopPlugin Example: Loop Over Array Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/api-reference/Plugins.md Demonstrates how to use LoopPlugin to iterate over an array of objects. The template syntax {#items}{name} - ${price}{/items} is used with the provided data. ```typescript // Template: {#items}{name} - ${price}{/items} const data = { items: [ { name: 'Apple', price: 1.50 }, { name: 'Banana', price: 0.75 } ] }; // Output: "Apple - $1.50" and "Banana - $0.75" ``` -------------------------------- ### OpenXmlPart.xmlRoot Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/api-reference/Office.md Gets the root XML element of the part. This allows for direct manipulation or inspection of the part's XML structure. ```APIDOC ## Method: xmlRoot ```typescript public async xmlRoot(): Promise ``` ### Description Gets the root XML element of the part. ### Return Type `Promise` - XML root node of the part ### Example ```typescript const part = docx.mainDocument; const xmlRoot = await part.xmlRoot(); console.log('Root tag:', xmlRoot.nodeName); console.log('Child nodes:', xmlRoot.childNodes.length); ``` ``` -------------------------------- ### Scope Resolution Example Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/README.md Demonstrates how data scope resolution works, allowing inner scopes to access values from outer scopes in templates. ```typescript const data = { companyName: 'ACME', // Top-level scope departments: [ { name: 'Sales', employees: [ { name: 'Alice' } // Can access companyName here ] } ] }; // Template in employee loop can reference {companyName} ``` -------------------------------- ### ImagePlugin Example: Inline Image Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/api-reference/Plugins.md Demonstrates embedding an inline image using ImagePlugin. Requires 'source', 'format', 'width', and 'height' properties. The template tag is replaced with the image markup. ```typescript const data = { logo: { _type: 'image', source: fs.readFileSync('logo.png'), format: 'image/png', width: 200, height: 100, altText: 'Company Logo' } }; // Template tag: {logo} gets replaced with inline image ``` -------------------------------- ### Loop Plugin Example Source: https://github.com/alonrbar/easy-template-x/blob/master/README.md The Loop plugin iterates over text, table rows, or columns. It requires opening and closing tags, with the closing tag optionally matching the opening tag's name. ```json { "Beers": [ { "Brand": "Carlsberg", "Price": 1 }, { "Brand": "Leaf Blonde", "Price": 2 }, { "Brand": "Weihenstephan", "Price": 1.5 } ] } ``` -------------------------------- ### Default Content Type Usage Example Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/api-reference/TemplateHandlerOptions.md Demonstrates how defaultContentType handles primitive data types like strings and numbers when no explicit type is provided in the template. ```typescript // Both do the same thing with default options const handler = new TemplateHandler(); const data = { name: 'John', // Uses defaultContentType = 'text' count: 42 // Uses defaultContentType = 'text' }; await handler.process(templateFile, data); ``` -------------------------------- ### Email-style Delimiters Example Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/configuration.md Configures the TemplateHandler with email-style delimiters, often seen in server-side templating languages. Note that container tags can be words. ```typescript const handler = new TemplateHandler({ delimiters: { tagStart: "<%", tagEnd: "%>", containerTagOpen: "if", containerTagClose: "/if" } }); // Usage: <% name %> <% if items %>...<% /if %> ``` -------------------------------- ### Nested Conditions Example Source: https://github.com/alonrbar/easy-template-x/blob/master/README.md Supports nested conditions, allowing other tags including loops and conditions within them. Ensure data structure matches the nesting. ```javascript { "teams": [ { show: true, name: "A-Team", members: [ { name: "Hannibal" }, { name: "Face" }, { name: "Murdock" }, { name: "Baracus" }, ] }, { show: false, name: "B-Team", members: [ { name: "Alice" }, { name: "Bob" }, { name: "Charlie" }, { name: "Dave" }, ] } ], } ``` -------------------------------- ### Create Default Plugins - TypeScript Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/api-reference/Plugins.md Call `createDefaultPlugins` to get an array containing all six built-in plugins for easy-template-x. This function ensures plugins are initialized in the correct order for processing. ```typescript import { createDefaultPlugins } from 'easy-template-x'; const allPlugins = createDefaultPlugins(); console.log(allPlugins.length); // 6 ``` -------------------------------- ### Production Configuration Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/configuration.md Configure TemplateHandler for production use with default plugins, custom content types, and specific delimiters. This setup optimizes for common production scenarios. ```typescript import { TemplateHandler, createDefaultPlugins } from 'easy-template-x'; const handler = new TemplateHandler({ plugins: createDefaultPlugins(), skipEmptyTags: false, defaultContentType: 'text', containerContentType: 'loop', delimiters: { tagStart: "{", tagEnd: "}", containerTagOpen: "#", containerTagClose: "/" }, maxXmlDepth: 20, extensions: {} }); ``` -------------------------------- ### Post-processing Extension Example Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/api-reference/Extensions.md This extension performs cleanup after tag compilation by removing empty tags, such as empty 'w:r' (run) nodes, that might be left over. It queries for these empty nodes and removes them from the XML structure. ```typescript export class PostprocessingExtension extends TemplateExtension { public async execute(data: ScopeData, context: TemplateContext): Promise { const xmlRoot = await context.currentPart.xmlRoot(); const maxDepth = context.options.maxXmlDepth; // Find and clean up empty tags left after compilation const emptyRuns = xml.query.descendants( xmlRoot, maxDepth, node => { if (!xml.query.isGeneralNode(node) || node.nodeName !== 'w:r') { return false; } const textNodes = node.childNodes?.filter( c => xml.query.isGeneralNode(c) && c.nodeName === 'w:t' ) || []; return textNodes.length === 0; } ); // Remove empty runs for (const run of emptyRuns) { xml.modify.remove(run); } } } ``` -------------------------------- ### Style Preprocessing Extension Example Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/api-reference/Extensions.md This extension modifies XML before tag compilation, specifically targeting paragraphs to apply preprocessing. It queries for paragraph nodes and then applies custom styling or formatting. ```typescript export class StylePreprocessor extends TemplateExtension { public async execute(data: ScopeData, context: TemplateContext): Promise { const xmlRoot = await context.currentPart.xmlRoot(); const maxDepth = context.options.maxXmlDepth; // Find all paragraphs const paragraphs = xml.query.descendants( xmlRoot, maxDepth, node => xml.query.isGeneralNode(node) && node.nodeName === 'w:p' ); // Apply preprocessing to each paragraph for (const para of paragraphs) { await this.applyStylePreprocessing(para); } } private async applyStylePreprocessing(para: any): Promise { // Add custom styling, formatting, etc. } } ``` -------------------------------- ### Implementing Before Compilation Hooks Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/README.md Add custom logic to execute before template compilation using extensions. This example demonstrates a validation hook to check for required data fields. ```typescript class ValidationExtension extends TemplateExtension { public async execute(data, context): Promise { const required = ['title', 'author']; for (const field of required) { if (!data.allData[field]) { throw new Error(`Missing required field: ${field}`); } } } } const handler = new TemplateHandler({ extensions: { beforeCompilation: [new ValidationExtension()] } }); ``` -------------------------------- ### Handle Container Tag Replacements Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/api-reference/Plugins.md Implement this method to process container tags (opening, closing, and nested content). The default is a no-op. This example demonstrates a simplified loop plugin that repeats content for each item in an array. ```typescript public async containerTagReplacements(tags: Tag[], data: ScopeData, context: TemplateContext): Promise { const value = data.getScopeData(); if (!Array.isArray(value)) { // Handle as condition return; } // Clone and repeat content for each array item const openTag = tags[0]; const closeTag = tags[tags.length - 1]; // ... content repetition logic ... } ``` -------------------------------- ### LoopPlugin Example: Loop With Table Rows Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/api-reference/Plugins.md Illustrates using LoopPlugin to repeat table rows based on an array of data. The `loopOver:row` option is used to repeat the entire table row. ```typescript // Template in table row: {#students[loopOver:row]}{name}{/} const data = { students: [ { name: 'Alice' }, { name: 'Bob' } ] }; // Output: Two rows in table, each with a student name ``` -------------------------------- ### Handle Simple Tag Replacements Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/api-reference/Plugins.md Implement this method to process self-closing tags. The default implementation is a no-op. This example shows how to replace the tag's content with a string value. ```typescript public simpleTagReplacements(tag: Tag, data: ScopeData): void { const value = data.getScopeData(); const strValue = stringValue(value); if (tag.placement === TagPlacement.TextNode) { const textNode = tag.xmlTextNode; textNode.textContent = strValue; } } ``` -------------------------------- ### RawXmlPlugin Example: Special Symbol Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/api-reference/Plugins.md Example of using RawXmlPlugin to insert a special symbol using its font and character code. ```typescript const data = { checkmark: { _type: 'rawXml', xml: '' } }; ``` -------------------------------- ### Project File Organization Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/INDEX.md This snippet shows the directory structure of the Easy Template X project, highlighting the purpose of key files and directories. ```text /workspace/home/output/ ├── README.md # Start here - overview and index ├── INDEX.md # This file - navigation guide ├── types.md # All exported types ├── configuration.md # Configuration options ├── errors.md # Error types and handling └── api-reference/ ├── TemplateHandler.md # Main entry point ├── TemplateHandlerOptions.md # Configuration class ├── Plugins.md # Plugin system ├── Extensions.md # Extension system ├── Office.md # DOCX structure API └── Constants.md # Exported constants ``` -------------------------------- ### Import Options and Plugins Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/INDEX.md Import options and default plugin creation functions. ```typescript // Options and plugins import { TemplateHandlerOptions, createDefaultPlugins } from 'easy-template-x'; ``` -------------------------------- ### ChartPlugin Example: Scatter Chart Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/api-reference/Plugins.md Example data structure for a scatter chart, where data points are represented by x and y coordinates. ```typescript const data = { scatter: { _type: 'chart', series: [ { name: 'Group A', values: [ { x: 1, y: 10 }, { x: 2, y: 20 }, { x: 3, y: 15 } ] } ] } }; ``` -------------------------------- ### Default Scope Resolution Example Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/configuration.md Demonstrates the default scope resolution behavior, which allows using values from outer scopes within loops. This enables accessing parent scope data like 'companyName' inside an 'employees' loop. ```typescript const data = { companyName: 'ACME Corp', employees: [ { name: 'Alice' }, { name: 'Bob' } ] }; // Default resolver allows: // {#employees} // {name} works for {companyName} // {/} // Output: "Alice works for ACME Corp", "Bob works for ACME Corp" const handler = new TemplateHandler(); await handler.process(templateFile, data); ``` -------------------------------- ### Docx.open Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/api-reference/Office.md Opens a DOCX file from an already-loaded ZIP instance. This static method is used to initialize a Docx object from a Zip instance. ```APIDOC ## Static Method: open ### Description Opens a DOCX file from an already-loaded ZIP instance. ### Method `static async open(zip: Zip): Promise` ### Parameters #### Path Parameters - **zip** (Zip) - Required - Loaded ZIP file ### Throws - `MalformedFileError` if ZIP structure is not a valid DOCX ### Example ```typescript import { Zip, Docx } from 'easy-template-x'; const zip = await Zip.load(file); const docx = await Docx.open(zip); ``` ``` -------------------------------- ### RawXmlContent Usage Example Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/types.md Example of using RawXmlContent to insert a page break. Setting 'replaceParagraph' to true replaces the parent paragraph element. ```typescript const data = { pageBreak: { _type: 'rawXml', xml: '', replaceParagraph: true } }; ``` -------------------------------- ### Content Types with Plugins Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/README.md Illustrates various content types handled by Easy Template X plugins, including text, images, links, charts, and raw XML. ```typescript { // TextPlugin (default for primitives) name: 'John Doe', // ImagePlugin logo: { _type: 'image', source: imageBuffer, format: 'image/png', width: 200, height: 100 }, // LinkPlugin homepage: { _type: 'link', text: 'Visit us', target: 'https://example.com' }, // ChartPlugin salesChart: { _type: 'chart', categories: { names: ['Q1', 'Q2', 'Q3'] }, series: [{ name: 'Revenue', values: [100, 150, 200] }] }, // RawXmlPlugin pageBreak: { _type: 'rawXml', xml: '' } } ``` -------------------------------- ### Initialize TemplateHandler Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/api-reference/TemplateHandler.md Demonstrates basic and custom initialization of the TemplateHandler. Use custom options to configure plugins, max XML depth, and tag delimiters. ```typescript import { TemplateHandler } from 'easy-template-x'; // Basic initialization with defaults const handler = new TemplateHandler(); ``` ```typescript const handler = new TemplateHandler({ plugins: createDefaultPlugins(), maxXmlDepth: 25, delimiters: { tagStart: '{{', tagEnd: '}}' } }); ``` -------------------------------- ### Default Scope Resolution Example Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/api-reference/TemplateHandlerOptions.md Demonstrates how the default scopeDataResolver allows accessing outer scope variables within loops. This example shows accessing 'companyName' from the root scope inside an 'employees' loop. ```typescript const data = { companyName: 'ACME Corp', employees: [ { name: 'Alice' }, { name: 'Bob' } ] }; // Default resolver allows accessing companyName inside employees loop: // Template: {#employees}{name} works for {companyName}{/} // Output: "Alice works for ACME Corp" and "Bob works for ACME Corp" const handler = new TemplateHandler(); await handler.process(templateFile, data); ``` -------------------------------- ### Catching TemplateSyntaxError Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/errors.md Example of how to catch and handle TemplateSyntaxError during template processing. This is useful for debugging malformed templates. ```typescript try { const result = await handler.process(templateFile, data); } catch (error) { if (error instanceof TemplateSyntaxError) { console.error('Template syntax error:', error.message); } } ``` -------------------------------- ### LoopOver Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/api-reference/Constants.md Options for controlling what gets repeated in a loop. This enumeration defines the possible values for the `loopOver` directive. ```APIDOC ## LoopOver ### Description Options for controlling what gets repeated in a loop. This enumeration defines the possible values for the `loopOver` directive. ### Constants | Constant | Value | Behavior | |----------|-------|----------| | Row | 'row' | Repeat entire table row | | Column | 'column' | Repeat entire table column | | Paragraph | 'paragraph' | Repeat entire paragraph | | Content | 'content' | Repeat content between tags (default) | ### Usage ```typescript import { LoopOver } from 'easy-template-x'; const data = { // Template: {#students[loopOver:row]}...{/} students: [ { name: 'Alice' }, { name: 'Bob' } ] }; // With loopOver: 'row', entire table row is repeated for each student ``` ``` -------------------------------- ### Catch TemplateDataError Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/errors.md Example of how to catch and handle TemplateDataError during template processing. This is useful for diagnosing issues with input data. ```typescript try { const result = await handler.process(templateFile, data); } catch (error) { if (error instanceof TemplateDataError) { console.error('Template data error:', error.message); } } ``` -------------------------------- ### Interface: ExtensionOptions Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/api-reference/Extensions.md Defines the structure for specifying which extensions to use, categorized into `beforeCompilation` and `afterCompilation`. ```APIDOC ## Interface: ExtensionOptions ### Description Specifies which extensions to use. ### Fields #### beforeCompilation - **beforeCompilation** (`TemplateExtension[]`) - Optional - Extensions to run before tag compilation #### afterCompilation - **afterCompilation** (`TemplateExtension[]`) - Optional - Extensions to run after tag compilation ### Execution Order For each content part: 1. Load XML 2. **Run beforeCompilation extensions in order** 3. Compile tags with plugins 4. **Run afterCompilation extensions in order** 5. Save XML ### Example ```typescript const options = { beforeCompilation: [ new PreprocessExtension(), new ValidationExtension() ], afterCompilation: [ new PostprocessExtension() ] }; ``` ``` -------------------------------- ### Catch MalformedFileError Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/errors.md Example of how to catch and handle MalformedFileError when processing an invalid DOCX file. This is useful for validating file integrity. ```typescript const invalidFile = Buffer.from('not a valid docx'); try { const result = await handler.process(invalidFile, data); } catch (error) { if (error instanceof MalformedFileError) { console.error('Invalid DOCX file:', error.message); } } ``` -------------------------------- ### Process DOCX Template in Browser Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/api-reference/TemplateHandler.md This browser-compatible snippet demonstrates fetching a DOCX template using the Fetch API, processing it with provided data, and initiating a download of the result. ```typescript import { TemplateHandler } from 'easy-template-x'; // Fetch template from server const response = await fetch('http://example.com/template.docx'); const templateFile = await response.blob(); const data = { title: 'Report', items: [{ name: 'A' }, { name: 'B' }] }; const handler = new TemplateHandler(); const doc = await handler.process(templateFile, data); // Download the document const url = URL.createObjectURL(doc); const link = document.createElement('a'); link.href = url; link.download = 'output.docx'; link.click(); ``` -------------------------------- ### Minimal Configuration Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/configuration.md Instantiate TemplateHandler with default settings. No specific configuration is required for basic usage. ```typescript import { TemplateHandler } from 'easy-template-x'; // Uses all defaults const handler = new TemplateHandler(); ``` -------------------------------- ### Define a Basic Logging Extension Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/configuration.md Create a custom extension that logs the processing of each part. This extension can be used to add custom logic before or after compilation. ```typescript class LoggingExtension extends TemplateExtension { public async execute(data: ScopeData, context: TemplateContext): Promise { console.log('Processing part:', context.currentPart.path); } } const handler = new TemplateHandler({ extensions: { beforeCompilation: [new LoggingExtension()], afterCompilation: [] } }); ``` -------------------------------- ### Configure Template Handler Options Source: https://github.com/alonrbar/easy-template-x/blob/master/README.md Instantiate TemplateHandler with various configuration options like plugins, content types, delimiters, and extensions. Default values are shown. ```typescript const handler = new TemplateHandler({ plugins: createDefaultPlugins(), // TemplatePlugin[] defaultContentType: TEXT_CONTENT_TYPE, // string containerContentType: LOOP_CONTENT_TYPE, // string delimiters: { // Partial tagStart: "{", tagEnd: "}", containerTagOpen: "#", containerTagClose: "/", tagOptionsStart: "[", tagOptionsEnd: "]" }, maxXmlDepth: 20, extensions: { // ExtensionOptions beforeCompilation: undefined, // TemplateExtension[] afterCompilation: undefined // TemplateExtension[] }, scopeDataResolver: undefined // ScopeDataResolver }) ``` -------------------------------- ### Get Library Version Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/api-reference/TemplateHandler.md Access the version property to retrieve the current version of the easy-template-x library. This value is set during compilation. ```typescript const handler = new TemplateHandler(); console.log('Library version:', handler.version); ``` -------------------------------- ### Extract Text from Part Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/api-reference/Office.md Use this method to get all plain text content from a document part. Ensure the part is loaded before calling. ```typescript const part = docx.mainDocument; const text = await part.getText(); console.log('Document text:', text); ``` -------------------------------- ### createDefaultPlugins Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/api-reference/Plugins.md A helper function to create an array containing all six built-in plugins in their correct order. ```APIDOC ## createDefaultPlugins() ### Description Creates an array with all six built-in plugins (Loop, RawXml, Chart, Image, Link, Text) in the correct order. ### Returns - Array of plugin instances. ``` -------------------------------- ### Configure Multiple Extensions Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/configuration.md Register multiple extensions for both pre- and post-compilation phases. Extensions are executed in the order they are provided in the arrays. ```typescript const handler = new TemplateHandler({ extensions: { beforeCompilation: [ new ValidationExtension(), new PreprocessingExtension() ], afterCompilation: [ new PostprocessingExtension() ] } }); ``` -------------------------------- ### Container Content Type Usage Example Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/api-reference/TemplateHandlerOptions.md Illustrates how containerContentType is used to process array iteration (loops) and conditional rendering within templates. ```typescript const handler = new TemplateHandler(); const data = { items: [ // Handled by containerContentType plugin { name: 'A' }, { name: 'B' } ], showDetails: true // Also handled by containerContentType (condition) }; // Template: {#items}{name}{/} {#showDetails}Details shown{/showDetails} await handler.process(templateFile, data); ``` -------------------------------- ### Initialize TemplateHandler with Default Options Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/configuration.md Basic initialization of TemplateHandler using default plugins and common configuration settings. ```typescript const handler = new TemplateHandler({ plugins: createDefaultPlugins(), skipEmptyTags: false, defaultContentType: 'text', containerContentType: 'loop', delimiters: { ... }, maxXmlDepth: 20, extensions: { ... }, scopeDataResolver: undefined }); ``` -------------------------------- ### Custom Delimiters for Tags Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/INDEX.md Instantiate TemplateHandler with custom tag delimiters. Use this when your template uses non-standard start and end characters for tags. ```typescript new TemplateHandler({ delimiters: { tagStart: '{{', tagEnd: '}}' } }) ``` -------------------------------- ### Abstract Method: execute Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/api-reference/Extensions.md The `execute` method is the core logic for any extension. Subclasses must implement this method to define their behavior. It can be synchronous or asynchronous. ```APIDOC ## Abstract Method: execute ```typescript public abstract execute(data: ScopeData, context: TemplateContext): void | Promise; ``` ### Description Executes the extension logic. Must be implemented by subclasses. ### Parameters #### Path Parameters - **data** (`ScopeData`) - Required - Scope data containing template data and path information - **context** (`TemplateContext`) - Required - Document context including DOCX file and current part ### Return Type `void | Promise` - Can be synchronous or asynchronous - Return a Promise if performing async operations ### Execution Context **For `beforeCompilation` extensions:** - Called before tags are processed - XML has not been modified yet - Can modify XML before tag compilation **For `afterCompilation` extensions:** - Called after all tags are processed - Can access results of tag compilation - Can perform post-processing ### Example ```typescript public async execute(data: ScopeData, context: TemplateContext): Promise { const xmlRoot = await context.currentPart.xmlRoot(); // Modify XML using xml utilities // Access template data via data.getScopeData() } ``` ``` -------------------------------- ### Configuring Extensions Source: https://github.com/alonrbar/easy-template-x/blob/master/README.md This code shows how to configure the TemplateHandler to use custom extensions. Extensions can be specified to run either after compilation or before compilation, allowing for custom document manipulation logic. ```javascript const handler = new TemplateHandler({ extensions: { afterCompilation: [ new DataBindingExtension() ] } }); ``` -------------------------------- ### Double Curly Braces Delimiters Example Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/configuration.md Configures the TemplateHandler to use double curly braces as delimiters. This can help avoid conflicts with HTML or other syntax. ```typescript const handler = new TemplateHandler({ delimiters: { tagStart: "{{", tagEnd: "}}", containerTagOpen: "#", containerTagClose: "/" } }); // Usage: {{name}} {{#items}}...{{/}} ``` -------------------------------- ### Load DOCX File Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/api-reference/Office.md Loads a DOCX file from binary data. Use this method when you have the DOCX file content as a Blob, Buffer, or ArrayBuffer. It returns a Promise that resolves to a Docx instance. ```typescript import * as fs from 'fs'; import { Docx } from 'easy-template-x'; const file = fs.readFileSync('template.docx'); const docx = await Docx.load(file); console.log('Main document:', docx.mainDocument.path); ``` -------------------------------- ### Import Office API Components Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/INDEX.md Import components related to the Office API for interacting with document structures. ```typescript // Office API import { Docx, OpenXmlPart, Relationship, RelType } from 'easy-template-x'; ``` -------------------------------- ### With Custom Data Resolver Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/configuration.md Implement a custom scope data resolver to control how data is accessed within templates. This example shows support for lodash-style paths. ```typescript import { TemplateHandler, ScopeData, ScopeDataArgs } from 'easy-template-x'; const handler = new TemplateHandler({ scopeDataResolver: (args: ScopeDataArgs) => { // Support lodash-style paths const lodash = require('lodash'); const path = args.strPath.join('.'); return lodash.get(args.data, path); } }); const data = { user: { profile: { fullName: 'John Doe' } } }; // Template: {user.profile.fullName} ``` -------------------------------- ### Docx.mediaFiles Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/api-reference/Office.md Manages media files (images, etc.) within the DOCX. Supports adding new media files and returns their paths. ```APIDOC ## Property: mediaFiles ### Description Manages media files (images, etc.) in the DOCX. ### Type `MediaFiles` ### Methods - `add(source: Binary, format: MimeType): Promise` - Add media file, returns path ### Example ```typescript const docx = await Docx.load(file); // Add an image to the document const imagePath = await docx.mediaFiles.add(imageBuffer, 'image/png'); console.log('Image added at:', imagePath); ``` ``` -------------------------------- ### Get XML Root Element of a Part Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/api-reference/Office.md Retrieves the root XML element of a DOCX part. Useful for inspecting or modifying the part's XML structure. ```typescript const part = docx.mainDocument; const xmlRoot = await part.xmlRoot(); console.log('Root tag:', xmlRoot.nodeName); console.log('Child nodes:', xmlRoot.childNodes.length); ``` -------------------------------- ### Import Types and Interfaces Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/INDEX.md Import various types and interfaces for template data and content. ```typescript // Types and interfaces import { TemplateData, ImageContent, LinkContent, ChartContent, RawXmlContent, Tag } from 'easy-template-x'; ``` -------------------------------- ### Import Main Handler Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/INDEX.md Import the main TemplateHandler class for processing templates. ```typescript // Main handler import { TemplateHandler } from 'easy-template-x'; ``` -------------------------------- ### Validate DOCX File Integrity Source: https://github.com/alonrbar/easy-template-x/blob/master/_autodocs/errors.md Before processing, check if the file is non-empty and starts with the ZIP magic bytes (0x50, 0x4B) to ensure it's a valid DOCX. ```typescript // Verify file is a valid DOCX before processing if (!file || file.length < 100) { throw new Error('Invalid file'); } // Check for ZIP magic bytes if (file[0] !== 0x50 || file[1] !== 0x4B) { throw new Error('File is not a valid DOCX'); } ```