easy-template-x
Generate docx documents from templates, in Node or in the browser.
Prior art and motivation
There are already some very good templating libraries out there, most notably these two:
easy-template-x
takes great inspiration from both. It aspires to take the best
out of both and to support some usecases that are not supported by either.
Specifically, it keeps the ease of use that docxtemplater
provides to the end
user and adds line break auto insertion which is currently missing there.
Internally it works more like docx-templates
than docxtemplater
in that
sense that it traverses xml documents node by node in a strongly typed manner rather than
using a text matching approach.
It was also inspired by docxtemplater
modules system and introduces a similar
plugins system. The main difference in that area is that the library is fully written
in TypeScript and the code base provides a lot of comments and explanation
inside, thus making it as easy as possible to write your own custom plugins.
Node Example
import * as fs from 'fs';
import { TemplateHandler } from 'easy-template-x';
const templateFile = fs.readFileSync('myTemplate.docx');
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);
fs.writeFileSync('myTemplate - output.docx', doc);
Input:
Output:
Browser Example
The following example produces the same output while running in the browser.
Notice that the actual template processing (step 2) is exactly the same as in the previous Node example.
import { TemplateHandler } from 'easy-template-x';
const response = await fetch('http://somewhere.com/myTemplate.docx');
const templateFile = await response.blob();
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);
saveFile('myTemplate - output.docx', doc);
function saveFile(filename, blob) {
const blobUrl = URL.createObjectURL(blob);
let link = document.createElement("a");
link.download = filename;
link.href = blobUrl;
document.body.appendChild(link);
link.click();
setTimeout(() => {
link.remove();
window.URL.revokeObjectURL(blobUrl);
link = null;
}, 0);
}
Writing your own plugins
To write a plugin inherit from the TemplatePlugin class.
The base class provides two methods you can implement and a set of utilities to
make it easier to do the actual xml modification.
Example plugin implementation (source):
export class RawXmlPlugin extends TemplatePlugin {
public readonly prefixes: TagPrefix[] = [{
prefix: '@',
tagType: 'rawXml',
tagDisposition: TagDisposition.SelfClosed
}];
public simpleTagReplacements(tag: Tag, data: ScopeData): void {
const wordTextNode = this.utilities.docxParser.containingTextNode(tag.xmlTextNode);
const value = data.getScopeData();
if (typeof value === 'string') {
const newNode = this.utilities.xmlParser.parse(value);
XmlNode.insertBefore(newNode, wordTextNode);
}
XmlNode.remove(wordTextNode);
}
}
API
TODO - Meanwhile, you can checkout the typings file.
Binary Formats
The library supports the following binary formats:
Limitations
Iterating table rows is currently not supported. Feel free to write your own plugin for that ;)
Changelog
The change log can be found here.