docxtemplater
Version:
.docx generator working with templates and data (like Mustache)
515 lines (484 loc) • 30.1 kB
JavaScript
"use strict";
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
var testUtils = require("./utils");
var expect = testUtils.expect;
var JSZip = require("jszip");
var Docxtemplater = require("../docxtemplater.js");
var DocUtils = require("../doc-utils.js");
var _ = require("lodash");
var inspectModule = require("./inspect-module.js");
var expressions = require("angular-expressions");
function angularParser(tag) {
var expr = expressions.compile(tag);
return {
get: function get(scope) {
return expr(scope);
}
};
}
describe("DocxtemplaterBasis", function () {
it("should be defined", function () {
expect(Docxtemplater).not.to.be.equal(undefined);
});
it("should construct", function () {
var doc = new Docxtemplater();
expect(doc).not.to.be.equal(undefined);
});
});
function getLength(obj) {
if (obj instanceof ArrayBuffer) {
return obj.byteLength;
}
return obj.length;
}
describe("DocxtemplaterLoading", function () {
describe("ajax done correctly", function () {
it("doc and img Data should have the expected length", function () {
var doc = testUtils.createDoc("image-example.docx");
expect(getLength(doc.loadedContent)).to.be.equal(729580);
expect(getLength(testUtils.imageData["image.png"])).to.be.equal(18062);
});
it("should have the right number of files (the docx unzipped)", function () {
var doc = testUtils.createDoc("image-example.docx");
expect(DocUtils.sizeOfObject(doc.zip.files)).to.be.equal(16);
});
});
describe("basic loading", function () {
it("should load file image-example.docx", function () {
var doc = testUtils.createDoc("image-example.docx");
expect(typeof doc === "undefined" ? "undefined" : _typeof(doc)).to.be.equal("object");
});
});
describe("content_loading", function () {
it("should load the right content for the footer", function () {
var doc = testUtils.createDoc("image-example.docx");
var fullText = doc.getFullText("word/footer1.xml");
expect(fullText.length).not.to.be.equal(0);
expect(fullText).to.be.equal("{last_name}{first_name}{phone}");
});
it("should load the right content for the document", function () {
var doc = testUtils.createDoc("image-example.docx");
// default value document.xml
var fullText = doc.getFullText();
expect(fullText).to.be.equal("");
});
it("should load the right template files for the document", function () {
var doc = testUtils.createDoc("tag-example.docx");
var templatedFiles = doc.getTemplatedFiles();
expect(templatedFiles).to.be.eql(["word/header1.xml", "word/footer1.xml", "word/document.xml"]);
});
});
describe("output and input", function () {
it("should be the same", function () {
var zip = new JSZip(testUtils.createDoc("tag-example.docx").loadedContent);
var doc = new Docxtemplater().loadZip(zip);
var output = doc.getZip().generate({ type: "base64" });
expect(output.length).to.be.equal(90732);
expect(output.substr(0, 50)).to.be.equal("UEsDBAoAAAAAAAAAIQAMTxYSlgcAAJYHAAATAAAAW0NvbnRlbn");
});
});
});
describe("DocxtemplaterTemplating", function () {
describe("text templating", function () {
it("should change values with template data", function () {
var tags = {
first_name: "Hipp",
last_name: "Edgar",
phone: "0652455478",
description: "New Website"
};
var doc = testUtils.createDoc("tag-example.docx");
doc.setData(tags);
doc.render();
expect(doc.getFullText()).to.be.equal("Edgar Hipp");
expect(doc.getFullText("word/header1.xml")).to.be.equal("Edgar Hipp0652455478New Website");
expect(doc.getFullText("word/footer1.xml")).to.be.equal("EdgarHipp0652455478");
testUtils.shouldBeSame({ doc: doc, expectedName: "tag-example-expected.docx" });
});
});
});
describe("inspect module", function () {
function getTags(postParsed) {
return postParsed.filter(function (part) {
return part.type === "placeholder";
}).reduce(function (tags, part) {
tags[part.value] = {};
if (part.subparsed) {
tags[part.value] = getTags(part.subparsed);
}
return tags;
}, {});
}
var doc = testUtils.createDoc("tag-loop-example.docx");
var iModule = inspectModule();
doc.attachModule(iModule);
doc.render();
var postParsed = iModule.fullInspected["word/document.xml"].postparsed;
var tags = getTags(postParsed);
expect(tags).to.be.deep.equal({
offre: {
nom: {},
prix: {},
titre: {}
},
nom: {},
prenom: {}
});
});
describe("DocxtemplaterTemplatingForLoop", function () {
describe("textLoop templating", function () {
it("should replace all the tags", function () {
var tags = {
nom: "Hipp",
prenom: "Edgar",
telephone: "0652455478",
description: "New Website",
offre: [{ titre: "titre1", prix: "1250" }, { titre: "titre2", prix: "2000" }, { titre: "titre3", prix: "1400", nom: "Offre" }]
};
var doc = testUtils.createDoc("tag-loop-example.docx");
doc.setData(tags);
doc.render();
expect(doc.getFullText()).to.be.equal("Votre proposition commercialeHippPrix: 1250Titre titre1HippPrix: 2000Titre titre2OffrePrix: 1400Titre titre3HippEdgar");
});
it("should work with loops inside loops", function () {
var tags = { products: [{ title: "Microsoft", name: "DOS", reference: "Win7", avantages: [{ title: "Everyone uses it", proof: [{ reason: "it is quite cheap" }, { reason: "it is quit simple" }, { reason: "it works on a lot of different Hardware" }] }] }, { title: "Linux", name: "Ubuntu", reference: "Ubuntu10", avantages: [{ title: "It's very powerful", proof: [{ reason: "the terminal is your friend" }, { reason: "Hello world" }, { reason: "it's free" }] }] }, { title: "Apple", name: "Mac", reference: "OSX", avantages: [{ title: "It's very easy", proof: [{ reason: "you can do a lot just with the mouse" }, { reason: "It's nicely designed" }] }] }] };
var doc = testUtils.createDoc("tag-produit-loop.docx");
doc.setData(tags);
doc.render();
var text = doc.getFullText();
var expectedText = "MicrosoftProduct name : DOSProduct reference : Win7Everyone uses itProof that it works nicely : It works because it is quite cheap It works because it is quit simple It works because it works on a lot of different HardwareLinuxProduct name : UbuntuProduct reference : Ubuntu10It's very powerfulProof that it works nicely : It works because the terminal is your friend It works because Hello world It works because it's freeAppleProduct name : MacProduct reference : OSXIt's very easyProof that it works nicely : It works because you can do a lot just with the mouse It works because It's nicely designed";
expect(text.length).to.be.equal(expectedText.length);
expect(text).to.be.equal(expectedText);
});
it("should not have sideeffects with inverted with array length 3", function () {
var content = "<w:t>{^todos}No {/todos}Todos</w:t><w:t>{#todos}{.}{/todos}</w:t>";
var expectedContent = '<w:t>Todos</w:t><w:t xml:space="preserve">ABC</w:t>';
var scope = { todos: ["A", "B", "C"] };
var xmlTemplater = testUtils.createXmlTemplaterDocx(content, { tags: scope });
xmlTemplater.render();
expect(xmlTemplater.content).to.be.deep.equal(expectedContent);
});
it("should not have sideeffects with inverted with empty array", function () {
var content = "<w:t>{^todos}No {/todos}Todos</w:t>\n\t\t\t<w:t>{#todos}{.}{/todos}</w:t>";
var expectedContent = "<w:t>No Todos</w:t>\n\t\t\t<w:t xml:space=\"preserve\"></w:t>";
var scope = { todos: [] };
var xmlTemplater = testUtils.createXmlTemplaterDocx(content, { tags: scope });
xmlTemplater.render();
expect(xmlTemplater.content).to.be.deep.equal(expectedContent);
});
it("should provide inverted loops", function () {
var content = "<w:t>{^products}No products found{/products}</w:t>";
[{ products: [] }, { products: false }, {}].forEach(function (tags) {
var doc = testUtils.createXmlTemplaterDocx(content, { tags: tags });
doc.render();
expect(doc.getFullText()).to.be.equal("No products found");
});
[{ products: [{ name: "Bread" }] }, { products: true }, { products: "Bread" }, { products: { name: "Bread" } }].forEach(function (tags) {
var doc = testUtils.createXmlTemplaterDocx(content, { tags: tags });
doc.render();
expect(doc.getFullText()).to.be.equal("");
});
});
it("should be possible to close loops with {/}", function () {
var content = "<w:t>{#products}Product {name}{/}</w:t>";
var tags = { products: [{ name: "Bread" }] };
var doc = testUtils.createXmlTemplaterDocx(content, { tags: tags });
doc.render();
expect(doc.getFullText()).to.be.equal("Product Bread");
});
it("should be possible to close double loops with {/}", function () {
var content = "<w:t>{#companies}{#products}Product {name}{/}{/}</w:t>";
var tags = { companies: [{ products: [{ name: "Bread" }] }] };
var doc = testUtils.createXmlTemplaterDocx(content, { tags: tags });
doc.render();
expect(doc.getFullText()).to.be.equal("Product Bread");
});
it("should work with complex loops", function () {
var content = "<w:t>{title} {#users} {name} friends are : {#friends} {.</w:t>TAG..TAG<w:t>},{/friends} {/users</w:t>TAG2<w:t>}</w:t>";
var scope = { title: "###Title###", users: [{ name: "John Doe", friends: ["Jane", "Henry"] }, {}], name: "Default", friends: ["None"] };
var doc = testUtils.createXmlTemplaterDocx(content, { tags: scope });
doc.render();
expect(doc.getFullText()).to.be.equal("###Title### John Doe friends are : Jane, Henry, Default friends are : None, ");
});
});
});
describe("Dash Loop Testing", function () {
it("dash loop ok on simple table -> w:tr", function () {
var tags = { os: [{ type: "linux", price: "0", reference: "Ubuntu10" }, { type: "DOS", price: "500", reference: "Win7" }, { type: "apple", price: "1200", reference: "MACOSX" }] };
var doc = testUtils.createDoc("tag-dash-loop.docx");
doc.setData(tags);
doc.render();
var expectedText = "linux0Ubuntu10DOS500Win7apple1200MACOSX";
var text = doc.getFullText();
expect(text).to.be.equal(expectedText);
});
it("dash loop ok on simple table -> w:table", function () {
var tags = { os: [{ type: "linux", price: "0", reference: "Ubuntu10" }, { type: "DOS", price: "500", reference: "Win7" }, { type: "apple", price: "1200", reference: "MACOSX" }] };
var doc = testUtils.createDoc("tag-dash-loop-table.docx");
doc.setData(tags);
doc.render();
var expectedText = "linux0Ubuntu10DOS500Win7apple1200MACOSX";
var text = doc.getFullText();
expect(text).to.be.equal(expectedText);
});
it("dash loop ok on simple list -> w:p", function () {
var tags = { os: [{ type: "linux", price: "0", reference: "Ubuntu10" }, { type: "DOS", price: "500", reference: "Win7" }, { type: "apple", price: "1200", reference: "MACOSX" }] };
var doc = testUtils.createDoc("tag-dash-loop-list.docx");
doc.setData(tags);
doc.render();
var expectedText = "linux 0 Ubuntu10 DOS 500 Win7 apple 1200 MACOSX ";
var text = doc.getFullText();
expect(text).to.be.equal(expectedText);
});
});
describe("Intelligent Loop Tagging", function () {
it("should work with tables", function () {
var tags = { clients: [{ first_name: "John", last_name: "Doe", phone: "+33647874513" }, { first_name: "Jane", last_name: "Doe", phone: "+33454540124" }, { first_name: "Phil", last_name: "Kiel", phone: "+44578451245" }, { first_name: "Dave", last_name: "Sto", phone: "+44548787984" }] };
var doc = testUtils.createDoc("tag-intelligent-loop-table.docx");
doc.setData(tags);
doc.render();
var expectedText = "JohnDoe+33647874513JaneDoe+33454540124PhilKiel+44578451245DaveSto+44548787984";
var text = doc.getFullText();
expect(text).to.be.equal(expectedText);
testUtils.shouldBeSame({ doc: doc, expectedName: "tag-intelligent-loop-table-expected.docx" });
});
it("should not do anything special when loop outside of table", function () {
["<w:t>{#tables}</w:t><w:table><w:tr><w:tc><w:t>{user}</w:t></w:tc></w:tr></w:table><w:t>{/tables}</w:t>"].forEach(function (content) {
var scope = {
tables: [{ user: "John" }, { user: "Jane" }]
};
var doc = testUtils.createXmlTemplaterDocx(content, { tags: scope });
doc.render();
expect(doc.content).to.be.equal('<w:t></w:t><w:table><w:tr><w:tc><w:t xml:space="preserve">John</w:t></w:tc></w:tr></w:table><w:t></w:t><w:table><w:tr><w:tc><w:t xml:space="preserve">Jane</w:t></w:tc></w:tr></w:table><w:t></w:t>');
});
});
});
describe("Changing the parser", function () {
it("should work with uppercassing", function () {
var content = "<w:t>Hello {name}</w:t>";
var scope = { name: "Edgar" };
function parser(tag) {
return _defineProperty({}, "get", function get(scope) {
return scope[tag].toUpperCase();
});
}
var xmlTemplater = testUtils.createXmlTemplaterDocx(content, { tags: scope, parser: parser });
xmlTemplater.render();
expect(xmlTemplater.getFullText()).to.be.equal("Hello EDGAR");
});
it("should work when setting from the Docxtemplater interface", function () {
var doc = testUtils.createDoc("tag-example.docx");
var zip = new JSZip(doc.loadedContent);
var d = new Docxtemplater().loadZip(zip);
var tags = {
first_name: "Hipp",
last_name: "Edgar",
phone: "0652455478",
description: "New Website"
};
d.setData(tags);
d.parser = function (tag) {
return _defineProperty({}, "get", function get(scope) {
return scope[tag].toUpperCase();
});
};
d.render();
expect(d.getFullText()).to.be.equal("EDGAR HIPP");
expect(d.getFullText("word/header1.xml")).to.be.equal("EDGAR HIPP0652455478NEW WEBSITE");
expect(d.getFullText("word/footer1.xml")).to.be.equal("EDGARHIPP0652455478");
});
it("should work with angular parser", function () {
var tags = { person: { first_name: "Hipp", last_name: "Edgar", birth_year: 1955, age: 59 } };
var doc = testUtils.createDoc("angular-example.docx");
doc.setData(tags);
doc.parser = angularParser;
doc.render();
expect(doc.getFullText()).to.be.equal("Hipp Edgar 2014");
});
it("should work with loops", function () {
var content = "<w:t>Hello {#person.adult}you{/person.adult}</w:t>";
var scope = { person: { name: "Edgar", adult: true } };
var xmlTemplater = testUtils.createXmlTemplaterDocx(content, { tags: scope, parser: angularParser });
xmlTemplater.render();
expect(xmlTemplater.getFullText()).to.be.equal("Hello you");
});
});
describe("Special characters", function () {
it("should parse placeholder containing special characters", function () {
var content = "<w:t>Hello {>name}</w:t>";
var scope = { ">name": "Edgar" };
var xmlTemplater = testUtils.createXmlTemplaterDocx(content, { tags: scope });
xmlTemplater.render();
expect(xmlTemplater.content).to.be.deep.equal('<w:t xml:space="preserve">Hello Edgar</w:t>');
});
it("should render placeholder containing special characters", function () {
var content = "<w:t>Hello {name}</w:t>";
var scope = { name: "<Edgar>" };
var xmlTemplater = testUtils.createXmlTemplaterDocx(content, { tags: scope });
xmlTemplater.render();
expect(xmlTemplater.content).to.be.deep.equal('<w:t xml:space="preserve">Hello <Edgar></w:t>');
});
it("should read full text correctly", function () {
var doc = testUtils.createDoc("cyrillic.docx");
var fullText = doc.getFullText();
expect(fullText.charCodeAt(0)).to.be.equal(1024);
expect(fullText.charCodeAt(1)).to.be.equal(1050);
expect(fullText.charCodeAt(2)).to.be.equal(1048);
expect(fullText.charCodeAt(3)).to.be.equal(1046);
expect(fullText.charCodeAt(4)).to.be.equal(1044);
expect(fullText.charCodeAt(5)).to.be.equal(1045);
expect(fullText.charCodeAt(6)).to.be.equal(1039);
expect(fullText.charCodeAt(7)).to.be.equal(1040);
});
it("should still read full text after applying tags", function () {
var doc = testUtils.createDoc("cyrillic.docx");
doc.setData({ name: "Edgar" });
doc.render();
var fullText = doc.getFullText();
expect(fullText.charCodeAt(0)).to.be.equal(1024);
expect(fullText.charCodeAt(1)).to.be.equal(1050);
expect(fullText.charCodeAt(2)).to.be.equal(1048);
expect(fullText.charCodeAt(3)).to.be.equal(1046);
expect(fullText.charCodeAt(4)).to.be.equal(1044);
expect(fullText.charCodeAt(5)).to.be.equal(1045);
expect(fullText.charCodeAt(6)).to.be.equal(1039);
expect(fullText.charCodeAt(7)).to.be.equal(1040);
expect(fullText.indexOf("Edgar")).to.be.equal(9);
});
it("should insert russian characters", function () {
var russianText = [1055, 1091, 1087, 1082, 1080, 1085, 1072];
var russian = russianText.map(function (char) {
return String.fromCharCode(char);
}).join("");
var doc = testUtils.createDoc("tag-example.docx");
var zip = new JSZip(doc.loadedContent);
var d = new Docxtemplater().loadZip(zip);
d.setData({ last_name: russian });
d.render();
var outputText = d.getFullText();
expect(outputText.substr(0, 7)).to.be.equal(russian);
});
});
describe("Complex table example", function () {
it("should work with simple table", function () {
var doc = testUtils.createDoc("table-complex2-example.docx");
doc.setData({
table1: [{
t1data1: "t1-1row-data1",
t1data2: "t1-1row-data2",
t1data3: "t1-1row-data3",
t1data4: "t1-1row-data4"
}, {
t1data1: "t1-2row-data1",
t1data2: "t1-2row-data2",
t1data3: "t1-2row-data3",
t1data4: "t1-2row-data4"
}, {
t1data1: "t1-3row-data1",
t1data2: "t1-3row-data2",
t1data3: "t1-3row-data3",
t1data4: "t1-3row-data4"
}],
t1total1: "t1total1-data",
t1total2: "t1total2-data",
t1total3: "t1total3-data"
});
doc.render();
var fullText = doc.getFullText();
expect(fullText).to.be.equal("TABLE1COLUMN1COLUMN2COLUMN3COLUMN4t1-1row-data1t1-1row-data2t1-1row-data3t1-1row-data4t1-2row-data1t1-2row-data2t1-2row-data3t1-2row-data4t1-3row-data1t1-3row-data2t1-3row-data3t1-3row-data4TOTALt1total1-datat1total2-datat1total3-data");
});
it("should work with more complex table", function () {
// set the templateData
var doc = testUtils.createDoc("table-complex-example.docx");
doc.setData({
table2: [{
t2data1: "t2-1row-data1",
t2data2: "t2-1row-data2",
t2data3: "t2-1row-data3",
t2data4: "t2-1row-data4"
}, {
t2data1: "t2-2row-data1",
t2data2: "t2-2row-data2",
t2data3: "t2-2row-data3",
t2data4: "t2-2row-data4"
}],
t1total1: "t1total1-data",
t1total2: "t1total2-data",
t1total3: "t1total3-data",
t2total1: "t2total1-data",
t2total2: "t2total2-data",
t2total3: "t2total3-data"
});
doc.render();
var fullText = doc.getFullText();
expect(fullText).to.be.equal("TABLE1COLUMN1COLUMN2COLUMN3COLUMN4TOTALt1total1-datat1total2-datat1total3-dataTABLE2COLUMN1COLUMN2COLUMN3COLUMN4t2-1row-data1t2-1row-data2t2-1row-data3t2-1row-data4t2-2row-data1t2-2row-data2t2-2row-data3t2-2row-data4TOTALt2total1-datat2total2-datat2total3-data");
});
it("should work when looping inside tables", function () {
var tags = {
table1: [1],
key: "value"
};
var template = "<w:tr>\n\t\t<w:tc><w:t>{#table1}Hi</w:t></w:tc>\n\t\t<w:tc><w:t>{/table1}</w:t> </w:tc>\n\t\t</w:tr>\n\t\t<w:tr>\n\t\t<w:tc><w:t>{#table1}Ho</w:t></w:tc>\n\t\t<w:tc><w:p><w:t>{/table1}</w:t> </w:p>\n\t\t</w:tc>\n\t\t</w:tr>\n\t\t<w:t>{key}</w:t>\n\t\t";
var doc = testUtils.createXmlTemplaterDocx(template, { tags: tags });
doc.render();
var fullText = doc.getFullText();
expect(fullText).to.be.equal("HiHovalue");
var expected = "<w:tr>\n\t\t<w:tc><w:t>Hi</w:t></w:tc>\n\t\t<w:tc><w:t></w:t> </w:tc>\n\t\t</w:tr>\n\t\t<w:tr>\n\t\t<w:tc><w:t>Ho</w:t></w:tc>\n\t\t<w:tc><w:p><w:t></w:t> </w:p>\n\t\t</w:tc>\n\t\t</w:tr>\n\t\t<w:t xml:space=\"preserve\">value</w:t>\n\t\t";
expect(doc.content).to.be.equal(expected);
});
});
describe("Raw Xml Insertion", function () {
it("should work with simple example", function () {
var inner = "<w:p><w:r><w:t>{@complexXml}</w:t></w:r></w:p>";
var content = "<w:document>" + inner + "</w:document>";
var scope = { complexXml: "<w:p w:rsidR=\"00612058\" w:rsidRDefault=\"00EA4B08\" w:rsidP=\"00612058\"><w:pPr><w:rPr><w: color w: val=\"FF0000\"/></w:rPr></w:pPr><w:r><w:rPr><w: color w: val=\"FF0000\"/></w:rPr><w:t>My custom XML</w:t></w:r></w:p><w:tbl><w:tblPr><w:tblStyle w: val=\"Grilledutableau\"/><w:tblW w: w=\"0\" w:type=\"auto\"/><w:tblLook w: val=\"04A0\" w: firstRow=\"1\" w: lastRow=\"0\" w: firstColumn=\"1\" w: lastColumn=\"0\" w: noHBand=\"0\" w: noVBand=\"1\"/></w:tblPr><w:tblGrid><w: gridCol w: w=\"2952\"/><w: gridCol w: w=\"2952\"/><w: gridCol w: w=\"2952\"/></w:tblGrid><w:tr w:rsidR=\"00EA4B08\" w:rsidTr=\"00EA4B08\"><w:tc><w:tcPr><w:tcW w: w=\"2952\" w:type=\"dxa\"/><w: shd w: val=\"clear\" w: color=\"auto\" w: fill=\"DDD9C3\" w:themeFill=\"background2\" w:themeFillShade=\"E6\"/></w:tcPr><w:p w:rsidR=\"00EA4B08\" w:rsidRPr=\"00EA4B08\" w:rsidRDefault=\"00EA4B08\" w:rsidP=\"00612058\"><w:pPr><w:rPr><w: b/><w: color w: val=\"000000\" w:themeColor=\"text1\"/></w:rPr></w:pPr><w:r><w:rPr><w: b/><w: color w: val=\"000000\" w:themeColor=\"text1\"/></w:rPr><w:t>Test</w:t></w:r></w:p></w:tc><w:tc><w:tcPr><w:tcW w: w=\"2952\" w:type=\"dxa\"/><w: shd w: val=\"clear\" w: color=\"auto\" w: fill=\"DDD9C3\" w:themeFill=\"background2\" w:themeFillShade=\"E6\"/></w:tcPr><w:p w:rsidR=\"00EA4B08\" w:rsidRPr=\"00EA4B08\" w:rsidRDefault=\"00EA4B08\" w:rsidP=\"00612058\"><w:pPr><w:rPr><w: b/><w: color w: val=\"FF0000\"/></w:rPr></w:pPr><w:r><w:rPr><w: b/><w: color w: val=\"FF0000\"/></w:rPr><w:t>Xml</w:t></w:r></w:p></w:tc><w:tc><w:tcPr><w:tcW w: w=\"2952\" w:type=\"dxa\"/><w: shd w: val=\"clear\" w: color=\"auto\" w: fill=\"DDD9C3\" w:themeFill=\"background2\" w:themeFillShade=\"E6\"/></w:tcPr><w:p w:rsidR=\"00EA4B08\" w:rsidRDefault=\"00EA4B08\" w:rsidP=\"00612058\"><w:pPr><w:rPr><w: color w: val=\"FF0000\"/></w:rPr></w:pPr><w:r><w:rPr><w: color w: val=\"FF0000\"/></w:rPr><w:t>Generated</w:t></w:r></w:p></w:tc></w:tr><w:tr w:rsidR=\"00EA4B08\" w:rsidTr=\"00EA4B08\"><w:tc><w:tcPr><w:tcW w: w=\"2952\" w:type=\"dxa\"/><w: shd w: val=\"clear\" w: color=\"auto\" w: fill=\"C6D9F1\" w:themeFill=\"text2\" w:themeFillTint=\"33\"/></w:tcPr><w:p w:rsidR=\"00EA4B08\" w:rsidRPr=\"00EA4B08\" w:rsidRDefault=\"00EA4B08\" w:rsidP=\"00612058\"><w:pPr><w:rPr><w: color w: val=\"000000\" w:themeColor=\"text1\"/><w: u w: val=\"single\"/></w:rPr></w:pPr><w:r w:rsidRPr=\"00EA4B08\"><w:rPr><w: color w: val=\"000000\" w:themeColor=\"text1\"/><w: u w: val=\"single\"/></w:rPr><w:t>Underline</w:t></w:r></w:p></w:tc><w:tc><w:tcPr><w:tcW w: w=\"2952\" w:type=\"dxa\"/><w: shd w: val=\"clear\" w: color=\"auto\" w: fill=\"C6D9F1\" w:themeFill=\"text2\" w:themeFillTint=\"33\"/></w:tcPr><w:p w:rsidR=\"00EA4B08\" w:rsidRDefault=\"00EA4B08\" w:rsidP=\"00612058\"><w:pPr><w:rPr><w: color w: val=\"FF0000\"/></w:rPr></w:pPr><w:r w:rsidRPr=\"00EA4B08\"><w:rPr><w: color w: val=\"FF0000\"/><w: highlight w: val=\"yellow\"/></w:rPr><w:t>Highlighting</w:t></w:r></w:p></w:tc><w:tc><w:tcPr><w:tcW w: w=\"2952\" w:type=\"dxa\"/><w: shd w: val=\"clear\" w: color=\"auto\" w: fill=\"C6D9F1\" w:themeFill=\"text2\" w:themeFillTint=\"33\"/></w:tcPr><w:p w:rsidR=\"00EA4B08\" w:rsidRPr=\"00EA4B08\" w:rsidRDefault=\"00EA4B08\" w:rsidP=\"00612058\"><w:pPr><w:rPr><w:rFonts w: ascii=\"Bauhaus 93\" w: hAnsi=\"Bauhaus 93\"/><w: color w: val=\"FF0000\"/></w:rPr></w:pPr><w:r w:rsidRPr=\"00EA4B08\"><w:rPr><w:rFonts w: ascii=\"Bauhaus 93\" w: hAnsi=\"Bauhaus 93\"/><w: color w: val=\"FF0000\"/></w:rPr><w:t>Font</w:t></w:r></w:p></w:tc></w:tr><w:tr w:rsidR=\"00EA4B08\" w:rsidTr=\"00EA4B08\"><w:tc><w:tcPr><w:tcW w: w=\"2952\" w:type=\"dxa\"/><w: shd w: val=\"clear\" w: color=\"auto\" w: fill=\"F2DBDB\" w:themeFill=\"accent2\" w:themeFillTint=\"33\"/></w:tcPr><w:p w:rsidR=\"00EA4B08\" w:rsidRDefault=\"00EA4B08\" w:rsidP=\"00EA4B08\"><w:pPr><w: jc w: val=\"center\"/><w:rPr><w: color w: val=\"FF0000\"/></w:rPr></w:pPr><w:r><w:rPr><w: color w: val=\"FF0000\"/></w:rPr><w:t>Centering</w:t></w:r></w:p></w:tc><w:tc><w:tcPr><w:tcW w: w=\"2952\" w:type=\"dxa\"/><w: shd w: val=\"clear\" w: color=\"auto\" w: fill=\"F2DBDB\" w:themeFill=\"accent2\" w:themeFillTint=\"33\"/></w:tcPr><w:p w:rsidR=\"00EA4B08\" w:rsidRPr=\"00EA4B08\" w:rsidRDefault=\"00EA4B08\" w:rsidP=\"00612058\"><w:pPr><w:rPr><w: i/><w: color w: val=\"FF0000\"/></w:rPr></w:pPr><w:r w:rsidRPr=\"00EA4B08\"><w:rPr><w: i/><w: color w: val=\"FF0000\"/></w:rPr><w:t>Italic</w:t></w:r></w:p></w:tc><w:tc><w:tcPr><w:tcW w: w=\"2952\" w:type=\"dxa\"/><w: shd w: val=\"clear\" w: color=\"auto\" w: fill=\"F2DBDB\" w:themeFill=\"accent2\" w:themeFillTint=\"33\"/></w:tcPr><w:p w:rsidR=\"00EA4B08\" w:rsidRDefault=\"00EA4B08\" w:rsidP=\"00612058\"><w:pPr><w:rPr><w: color w: val=\"FF0000\"/></w:rPr></w:pPr></w:p></w:tc></w:tr><w:tr w:rsidR=\"00EA4B08\" w:rsidTr=\"00EA4B08\"><w:tc><w:tcPr><w:tcW w: w=\"2952\" w:type=\"dxa\"/><w: shd w: val=\"clear\" w: color=\"auto\" w: fill=\"E5DFEC\" w:themeFill=\"accent4\" w:themeFillTint=\"33\"/></w:tcPr><w:p w:rsidR=\"00EA4B08\" w:rsidRDefault=\"00EA4B08\" w:rsidP=\"00612058\"><w:pPr><w:rPr><w: color w: val=\"FF0000\"/></w:rPr></w:pPr></w:p></w:tc><w:tc><w:tcPr><w:tcW w: w=\"2952\" w:type=\"dxa\"/><w: shd w: val=\"clear\" w: color=\"auto\" w: fill=\"E5DFEC\" w:themeFill=\"accent4\" w:themeFillTint=\"33\"/></w:tcPr><w:p w:rsidR=\"00EA4B08\" w:rsidRDefault=\"00EA4B08\" w:rsidP=\"00612058\"><w:pPr><w:rPr><w: color w: val=\"FF0000\"/></w:rPr></w:pPr></w:p></w:tc><w:tc><w:tcPr><w:tcW w: w=\"2952\" w:type=\"dxa\"/><w: shd w: val=\"clear\" w: color=\"auto\" w: fill=\"E5DFEC\" w:themeFill=\"accent4\" w:themeFillTint=\"33\"/></w:tcPr><w:p w:rsidR=\"00EA4B08\" w:rsidRDefault=\"00EA4B08\" w:rsidP=\"00612058\"><w:pPr><w:rPr><w: color w: val=\"FF0000\"/></w:rPr></w:pPr></w:p></w:tc></w:tr><w:tr w:rsidR=\"00EA4B08\" w:rsidTr=\"00EA4B08\"><w:tc><w:tcPr><w:tcW w: w=\"2952\" w:type=\"dxa\"/><w: shd w: val=\"clear\" w: color=\"auto\" w: fill=\"FDE9D9\" w:themeFill=\"accent6\" w:themeFillTint=\"33\"/></w:tcPr><w:p w:rsidR=\"00EA4B08\" w:rsidRDefault=\"00EA4B08\" w:rsidP=\"00612058\"><w:pPr><w:rPr><w: color w: val=\"FF0000\"/></w:rPr></w:pPr></w:p></w:tc><w:tc><w:tcPr><w:tcW w: w=\"2952\" w:type=\"dxa\"/><w: shd w: val=\"clear\" w: color=\"auto\" w: fill=\"FDE9D9\" w:themeFill=\"accent6\" w:themeFillTint=\"33\"/></w:tcPr><w:p w:rsidR=\"00EA4B08\" w:rsidRDefault=\"00EA4B08\" w:rsidP=\"00612058\"><w:pPr><w:rPr><w: color w: val=\"FF0000\"/></w:rPr></w:pPr></w:p></w:tc><w:tc><w:tcPr><w:tcW w: w=\"2952\" w:type=\"dxa\"/><w: shd w: val=\"clear\" w: color=\"auto\" w: fill=\"FDE9D9\" w:themeFill=\"accent6\" w:themeFillTint=\"33\"/></w:tcPr><w:p w:rsidR=\"00EA4B08\" w:rsidRDefault=\"00EA4B08\" w:rsidP=\"00612058\"><w:pPr><w:rPr><w: color w: val=\"FF0000\"/></w:rPr></w:pPr></w:p></w:tc></w:tr></w:tbl>" };
var doc = testUtils.createXmlTemplaterDocx(content, { tags: scope });
doc.render();
expect(doc.content.length).to.be.equal(content.length + scope.complexXml.length - inner.length);
expect(doc.content).to.contain(scope.complexXml);
});
it("should work even when tags are after the xml", function () {
var content = "<w:tbl>\n\t\t<w:tr>\n\t\t<w:tc>\n\t\t<w:p>\n\t\t<w:r>\n\t\t<w:t>{@complexXml}</w:t>\n\t\t</w:r>\n\t\t</w:p>\n\t\t</w:tc>\n\t\t</w:tr>\n\t\t<w:tr>\n\t\t<w:tc>\n\t\t<w:p>\n\t\t<w:r>\n\t\t<w:t>{name}</w:t>\n\t\t</w:r>\n\t\t</w:p>\n\t\t</w:tc>\n\t\t</w:tr>\n\t\t<w:tr>\n\t\t<w:tc>\n\t\t<w:p>\n\t\t<w:r>\n\t\t<w:t>{first_name}</w:t>\n\t\t</w:r>\n\t\t</w:p>\n\t\t</w:tc>\n\t\t</w:tr>\n\t\t<w:tr>\n\t\t<w:tc>\n\t\t<w:p>\n\t\t<w:r>\n\t\t<w:t>{#products} {year}</w:t>\n\t\t</w:r>\n\t\t</w:p>\n\t\t</w:tc>\n\t\t<w:tc>\n\t\t<w:p>\n\t\t<w:r>\n\t\t<w:t>{name}</w:t>\n\t\t</w:r>\n\t\t</w:p>\n\t\t</w:tc>\n\t\t<w:tc>\n\t\t<w:p>\n\t\t<w:r>\n\t\t<w:t>{company}{/products}</w:t>\n\t\t</w:r>\n\t\t</w:p>\n\t\t</w:tc>\n\t\t</w:tr>\n\t\t</w:tbl>\n\t\t";
var scope = {
complexXml: "<w:p><w:r><w:t>Hello</w:t></w:r></w:p>",
name: "John",
first_name: "Doe",
products: [{ year: 1550, name: "Moto", company: "Fein" }, { year: 1987, name: "Water", company: "Test" }, { year: 2010, name: "Bread", company: "Yu" }]
};
var doc = testUtils.createXmlTemplaterDocx(content, { tags: scope });
doc.render();
expect(doc.content).to.contain(scope.complexXml);
expect(doc.getFullText()).to.be.equal("HelloJohnDoe 1550MotoFein 1987WaterTest 2010BreadYu");
});
it("should work with closing tag in the form of <w:t>}{/body}</w:t>", function () {
var scope = { body: [{ paragraph: "hello" }] };
var content = "<w:t>{#body}</w:t>\n\t\t<w:t>{paragraph</w:t>\n\t\t\t<w:t>}{/body}</w:t>";
var xmlTemplater = testUtils.createXmlTemplaterDocx(content, { tags: scope });
xmlTemplater.render();
expect(xmlTemplater.content).not.to.contain("</w:t></w:t>");
});
it("should work with simple example and given options", function () {
var scope = { xmlTag: '<w:r><w:rPr><w:color w:val="FF0000"/></w:rPr><w:t>My custom</w:t></w:r><w:r><w:rPr><w:color w:val="00FF00"/></w:rPr><w:t>XML</w:t></w:r>' };
var doc = testUtils.createDoc("one-raw-xml-tag.docx");
doc.setOptions({
fileTypeConfig: _.merge({}, Docxtemplater.FileTypeConfig.docx, { tagRawXml: "w:r" })
});
doc.setData(scope);
doc.render();
expect(doc.getFullText()).to.be.equal("asdfMy customXMLqwery");
});
});
describe("pptx generation", function () {
it("should work with simple pptx", function () {
var doc = testUtils.createDoc("simple-example.pptx");
var p = doc.setData({ name: "Edgar" }).render();
expect(p.getFullText()).to.be.equal("Hello Edgar");
});
});
describe("Serialization", function () {
it("should be serialiazable", function () {
var doc = testUtils.createDoc("tag-example.docx");
JSON.stringify(doc);
});
});