shell bypass 403
"use strict";
function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }
function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
var _require = require("lodash"),
assign = _require.assign;
var expressionParser = require("../../expressions.js");
var expressionParserIE11 = require("../../expressions-ie11.js");
var Docxtemplater = require("../../docxtemplater.js");
var _require2 = require("../../utils.js"),
last = _require2.last;
var _require3 = require("../utils.js"),
createDocV4 = _require3.createDocV4,
createXmlTemplaterDocx = _require3.createXmlTemplaterDocx,
expect = _require3.expect,
expectToThrowSnapshot = _require3.expectToThrowSnapshot,
getContent = _require3.getContent,
getZip = _require3.getZip;
var inspectModule = require("../../inspect-module.js");
describe("Loading", function () {
describe("ajax done correctly", function () {
it("should have the right number of files (the docx unzipped)", function () {
var doc = createDocV4("tag-example.docx");
expect(Object.keys(doc.zip.files).length).to.be.equal(16);
});
});
describe("basic loading", function () {
it("should load file tag-example.docx", function () {
var doc = createDocV4("tag-example.docx");
expect(_typeof(doc)).to.be.equal("object");
});
});
describe("output and input", function () {
it("should be the same", function () {
var doc = createDocV4("tag-example.docx");
var output = doc.getZip().generate({
type: "base64"
});
expect(output.length).to.be.equal(90732);
expect(output.substr(0, 50)).to.be.equal("UEsDBAoAAAAAAAAAIQAMTxYSlgcAAJYHAAATAAAAW0NvbnRlbn");
});
});
});
describe("Retrieving text content", function () {
it("should work for the footer", function () {
var doc = createDocV4("tag-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 work for the document", function () {
var doc = createDocV4("tag-example.docx");
var fullText = doc.getFullText();
expect(fullText).to.be.equal("{last_name} {first_name}");
});
});
describe("Retrieving list of templated files", function () {
it("should return 6 templatedFiles for a simple document", function () {
var doc = createDocV4("tag-example.docx");
var templatedFiles = doc.getTemplatedFiles();
expect(templatedFiles).to.be.eql(["word/settings.xml", "docProps/core.xml", "docProps/app.xml", "word/header1.xml", "word/document.xml", "word/footer1.xml", "word/footnotes.xml"]);
});
});
describe("Api versioning", function () {
it("should work with valid numbers", function () {
var doc = createDocV4("tag-example.docx");
expect(doc.verifyApiVersion("3.6.0")).to.be.equal(true);
expect(doc.verifyApiVersion("3.5.0")).to.be.equal(true);
expect(doc.verifyApiVersion("3.4.2")).to.be.equal(true);
expect(doc.verifyApiVersion("3.4.22")).to.be.equal(true);
});
it("should fail with invalid versions", function () {
var doc = createDocV4("tag-example.docx");
expectToThrowSnapshot(doc.verifyApiVersion.bind(null, "5.0"));
expectToThrowSnapshot(doc.verifyApiVersion.bind(null, "5.6.0"));
expectToThrowSnapshot(doc.verifyApiVersion.bind(null, "3.44.0"));
expectToThrowSnapshot(doc.verifyApiVersion.bind(null, "3.41.100"));
});
});
describe("Inspect module", function () {
it("should get main tags", function () {
var iModule = inspectModule();
var doc = createDocV4("tag-loop-example.docx", {
modules: [iModule]
});
expect(iModule.getStructuredTags()).to.matchSnapshot();
expect(iModule.getTags()).to.be.deep.equal({
offre: {
nom: {},
prix: {},
titre: {}
},
nom: {},
prenom: {}
});
var data = {
offre: [{}],
prenom: "John"
};
doc.render(data);
var fi = iModule.fullInspected["word/document.xml"];
var _fi$nullValues = fi.nullValues,
summary = _fi$nullValues.summary,
detail = _fi$nullValues.detail;
var postparsed = fi.postparsed,
parsed = fi.parsed,
xmllexed = fi.xmllexed;
expect(postparsed.length).to.equal(249);
expect(parsed.length).to.equal(385);
expect(xmllexed.length).to.equal(383);
expect(iModule.inspect.tags).to.be.deep.equal(data);
expect(detail).to.be.an("array");
expect(detail[0].part.value).to.equal("nom");
expect(detail[0].scopeManager.scopeList[0].prenom).to.equal("John");
expect(summary).to.be.deep.equal([["offre", "nom"], ["offre", "prix"], ["offre", "titre"], ["nom"]]);
});
it("should get all tags (pptx file)", function () {
var iModule = inspectModule();
createDocV4("multi-page.pptx", {
modules: [iModule]
});
expect(iModule.getStructuredTags()).to.matchSnapshot();
expect(iModule.getFileType()).to.be.deep.equal("pptx");
expect(iModule.getAllTags()).to.be.deep.equal({
tag: {},
users: {
name: {}
}
});
expect(iModule.getTemplatedFiles().sort()).to.be.deep.equal(["ppt/slides/slide1.xml", "ppt/slides/slide2.xml", "ppt/slideLayouts/slideLayout1.xml", "ppt/slideLayouts/slideLayout10.xml", "ppt/slideLayouts/slideLayout11.xml", "ppt/slideLayouts/slideLayout12.xml", "ppt/slideLayouts/slideLayout2.xml", "ppt/slideLayouts/slideLayout3.xml", "ppt/slideLayouts/slideLayout4.xml", "ppt/slideLayouts/slideLayout5.xml", "ppt/slideLayouts/slideLayout6.xml", "ppt/slideLayouts/slideLayout7.xml", "ppt/slideLayouts/slideLayout8.xml", "ppt/slideLayouts/slideLayout9.xml", "ppt/slideMasters/slideMaster1.xml", "ppt/presentation.xml", "docProps/app.xml", "docProps/core.xml"].sort());
});
it("should get all tags and merge them", function () {
var iModule = inspectModule();
createDocV4("multi-page-to-merge.pptx", {
modules: [iModule]
});
expect(iModule.getAllTags()).to.be.deep.equal({
tag: {},
users: {
name: {},
age: {},
company: {}
}
});
});
it("should get all tags with additional data", function () {
var iModule = inspectModule();
createDocV4("tag-product-loop.docx", {
modules: [iModule]
});
expect(iModule.getAllStructuredTags()).to.be.deep.equal([{
type: "placeholder",
value: "products",
raw: "#products",
lIndex: 17,
sectPrCount: 0,
module: "loop",
inverted: false,
offset: 0,
lastParagrapSectPr: "",
endLindex: 216,
subparsed: [{
type: "placeholder",
value: "title",
offset: 11,
endLindex: 33,
lIndex: 33
}, {
type: "placeholder",
value: "name",
offset: 33,
endLindex: 57,
lIndex: 57
}, {
type: "placeholder",
value: "reference",
offset: 59,
endLindex: 74,
lIndex: 74
}, {
type: "placeholder",
value: "avantages",
module: "loop",
raw: "#avantages",
inverted: false,
offset: 70,
sectPrCount: 0,
lastParagrapSectPr: "",
endLindex: 192,
lIndex: 92,
subparsed: [{
type: "placeholder",
value: "title",
offset: 82,
endLindex: 108,
lIndex: 108
}, {
type: "placeholder",
value: "proof",
module: "loop",
raw: "#proof",
sectPrCount: 0,
lastParagrapSectPr: "",
inverted: false,
offset: 117,
endLindex: 174,
lIndex: 136,
subparsed: [{
type: "placeholder",
value: "reason",
offset: 143,
endLindex: 158,
lIndex: 158
}]
}]
}]
}]);
});
});
describe("Docxtemplater loops", function () {
it("should replace all the tags", function () {
var doc = createDocV4("tag-loop-example.docx");
doc.render({
nom: "Hipp",
prenom: "Edgar",
telephone: "0652455478",
description: "New Website",
offre: [{
titre: "titre1",
prix: "1260"
}, {
titre: "titre2",
prix: "2000"
}, {
titre: "titre3",
prix: "1400",
nom: "Offre"
}]
});
expect(doc.getFullText()).to.be.equal("Votre proposition commercialeHippPrix: 1260Titre 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 = createDocV4("tag-product-loop.docx");
doc.render(tags);
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 work with object value", function () {
var content = "<w:t>{#todo}{todo}{/todo}</w:t>";
var expectedContent = '<w:t xml:space="preserve">abc</w:t>';
var scope = {
todo: {
todo: "abc"
}
};
var xmlTemplater = createXmlTemplaterDocx(content, {
tags: scope
});
expect(getContent(xmlTemplater)).to.be.deep.equal(expectedContent);
});
it("should work with string value", function () {
var content = "<w:t>{#todo}{todo}{/todo}</w:t>";
var expectedContent = '<w:t xml:space="preserve">abc</w:t>';
var scope = {
todo: "abc"
};
var xmlTemplater = createXmlTemplaterDocx(content, {
tags: scope
});
var c = getContent(xmlTemplater);
expect(c).to.be.deep.equal(expectedContent);
});
it("should not have sideeffects with inverted with array length 3", function () {
var content = "<w:t>{^todos}No {/todos}Todos</w:t>\n<w:t>{#todos}{.}{/todos}</w:t>";
var expectedContent = "<w:t xml:space=\"preserve\">Todos</w:t>\n<w:t xml:space=\"preserve\">ABC</w:t>";
var scope = {
todos: ["A", "B", "C"]
};
var xmlTemplater = createXmlTemplaterDocx(content, {
tags: scope
});
var c = getContent(xmlTemplater);
expect(c).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<w:t>{#todos}{.}{/todos}</w:t>";
var expectedContent = "<w:t xml:space=\"preserve\">No Todos</w:t>\n\t\t<w:t/>";
var scope = {
todos: []
};
var xmlTemplater = createXmlTemplaterDocx(content, {
tags: scope
});
var c = getContent(xmlTemplater);
expect(c).to.be.deep.equal(expectedContent);
});
it("should provide inverted loops", function () {
var content = "<w:t>{^products}No products found{/products}</w:t>";
var samplesEmpty = [{
products: []
}, {
products: false
}, {}];
for (var _i2 = 0; _i2 < samplesEmpty.length; _i2++) {
var tags = samplesEmpty[_i2];
var doc = createXmlTemplaterDocx(content, {
tags: tags
});
expect(doc.getFullText()).to.be.equal("No products found");
}
var samples = [{
products: [{
name: "Bread"
}]
}, {
products: true
}, {
products: "Bread"
}, {
products: {
name: "Bread"
}
}];
for (var _i4 = 0; _i4 < samples.length; _i4++) {
var _tags = samples[_i4];
var _doc = createXmlTemplaterDocx(content, {
tags: _tags
});
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 = createXmlTemplaterDocx(content, {
tags: tags
});
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 = createXmlTemplaterDocx(content, {
tags: tags
});
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 = createXmlTemplaterDocx(content, {
tags: scope
});
expect(doc.getFullText()).to.be.equal("###Title### John Doe friends are : Jane, Henry, Default friends are : None, ");
});
});
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 = createXmlTemplaterDocx(content, {
tags: scope,
parser: parser
});
expect(xmlTemplater.getFullText()).to.be.equal("Hello EDGAR");
});
it("should work when setting from the Docxtemplater interface", function () {
var doc = createDocV4("tag-example.docx", {
parser: function parser(tag) {
return _defineProperty({}, "get", function get(scope) {
return scope[tag].toUpperCase();
});
}
});
doc.render({
first_name: "Hipp",
last_name: "Edgar",
phone: "0652455478",
description: "New Website"
});
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");
});
it("should work with expression parser", function () {
var tags = {
person: {
first_name: "Hipp",
last_name: "Edgar",
birth_year: 1955,
age: 59
}
};
var doc = createDocV4("angular-example.docx", {
parser: expressionParser
});
doc.render(tags);
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 = createXmlTemplaterDocx(content, {
tags: scope,
parser: expressionParser
});
expect(xmlTemplater.getFullText()).to.be.equal("Hello you");
});
it("should work with loops with expressionParser for ie 11", function () {
var content = "<w:t>Hello {#person.adult}you{/person.adult}</w:t>";
var scope = {
person: {
name: "Edgar",
adult: true
}
};
var xmlTemplater = createXmlTemplaterDocx(content, {
tags: scope,
parser: expressionParserIE11
});
expect(xmlTemplater.getFullText()).to.be.equal("Hello you");
});
it("should be able to access meta to get the index", function () {
var content = "<w:t>Hello {#users}{$index} {#$isFirst}@{/}{#$isLast}!{/}{name} {/users}</w:t>";
var scope = {
users: [{
name: "Jane"
}, {
name: "Mary"
}]
};
var xmlTemplater = createXmlTemplaterDocx(content, {
tags: scope,
parser: function parser(tag) {
return {
get: function get(scope, context) {
if (tag === "$index") {
return last(context.scopePathItem);
}
if (tag === "$isLast") {
var totalLength = context.scopePathLength[context.scopePathLength.length - 1];
var index = context.scopePathItem[context.scopePathItem.length - 1];
return index === totalLength - 1;
}
if (tag === "$isFirst") {
var _index = context.scopePathItem[context.scopePathItem.length - 1];
return _index === 0;
}
return scope[tag];
}
};
}
});
expect(xmlTemplater.getFullText()).to.be.equal("Hello 0 @Jane 1 !Mary ");
});
it("should be able to disable parent scope inheritance", function () {
var content = "<w:t>Hello {#users}{companyName}-{name} {/}</w:t>";
var scope = {
users: [{
name: "Jane"
}, {}],
companyName: "My company, should not be shown",
name: "Foo"
};
var xmlTemplater = createXmlTemplaterDocx(content, {
tags: scope,
nullGetter: function nullGetter(part) {
if (!part.module) {
return "NULL";
}
if (part.module === "rawxml") {
return "";
}
return "";
},
parser: function parser(tag) {
return {
get: function get(scope, context) {
if (context.num < context.scopePath.length) {
return null;
}
if (context.num > context.scopePath.length) {
throw new Error("Invalid context num");
}
return scope[tag];
}
};
}
});
expect(xmlTemplater.getFullText()).to.be.equal("Hello NULL-Jane NULL-NULL ");
});
it("should be able to retrieve parent scope with .. syntax and ... syntax", function () {
var content = "<w:t>{#loop}{#contractors}{...company} {..company} {company} {/}{/loop}</w:t>";
var tags = {
company: "Root company",
loop: [{
company: "ACME Company",
contractors: [{
company: "The other Company"
}, {
company: "Foobar Company"
}]
}]
};
var options = {
parser: function parser(tag) {
var matchesParent = /^(\.{2,})(.*)/g;
var parentCount = 0;
if (matchesParent.test(tag)) {
parentCount = tag.replace(matchesParent, "$1").length - 1;
tag = tag.replace(matchesParent, "$2");
}
return {
get: function get(scope, context) {
if (context.scopePath.length - context.num < parentCount) {
return null;
}
return scope[tag];
}
};
},
tags: tags
};
var doc = createXmlTemplaterDocx(content, options);
var fullText = doc.getFullText();
expect(fullText).to.be.equal("Root company ACME Company The other Company Root company ACME Company Foobar Company ");
});
it("should be able to have scopePathItem with different lengths when having conditions", function () {
var content = "<w:t>{#cond}{name}{/}</w:t>";
var scope = {
cond: true,
name: "John"
};
var innerContext = null;
var xmlTemplater = createXmlTemplaterDocx(content, {
tags: scope,
parser: function parser(tag) {
return {
get: function get(scope, context) {
if (tag === "name") {
innerContext = context;
}
return scope[tag];
}
};
}
});
expect(xmlTemplater.getFullText()).to.be.equal("John");
expect(innerContext.scopePath).to.be.deep.equal(["cond"]);
expect(innerContext.scopePathItem).to.be.deep.equal([0]);
expect(innerContext.scopeList.length).to.be.equal(2);
expect(innerContext.scopeList[0]).to.be.deep.equal(innerContext.scopeList[1]);
});
it("should call the parser just once", function () {
var calls = 0;
var content = "<w:t>{name}</w:t>";
var scope = {
name: "John"
};
createXmlTemplaterDocx(content, {
tags: scope,
parser: function parser(tag) {
return {
get: function get(scope) {
calls++;
return scope[tag];
}
};
}
});
expect(calls).to.equal(1);
});
it("should be able to access meta and context to get the type of tag", function () {
var content = "<w:p><w:t>Hello {#users}{name}{/users}</w:t></w:p>\n\t\t<w:p><w:t>{@rrr}</w:t></w:p>\n\t\t";
var scope = {
users: [{
name: "Jane"
}],
rrr: ""
};
var contexts = [];
var pX = [];
var xmlTemplater = createXmlTemplaterDocx(content, {
tags: scope,
parser: function parser(tag, x) {
pX.push(x);
return {
get: function get(scope, context) {
contexts.push(context);
if (tag === "$index") {
return last(context.scopePathItem);
}
return scope[tag];
}
};
}
});
expect(xmlTemplater.getFullText()).to.be.equal("Hello Jane");
var values = contexts.map(function (_ref3) {
var _ref3$meta$part = _ref3.meta.part,
type = _ref3$meta$part.type,
value = _ref3$meta$part.value,
module = _ref3$meta$part.module;
return {
type: type,
value: value,
module: module
};
});
expect(values).to.be.deep.equal([{
type: "placeholder",
value: "users",
module: "loop"
}, {
type: "placeholder",
value: "name",
module: undefined
}, {
type: "placeholder",
value: "rrr",
module: "rawxml"
}]);
expect(pX.map(function (_ref4) {
var _ref4$tag = _ref4.tag,
type = _ref4$tag.type,
value = _ref4$tag.value,
module = _ref4$tag.module;
return {
type: type,
value: value,
module: module
};
})).to.be.deep.equal([{
type: "placeholder",
value: "name",
module: undefined
}, {
type: "placeholder",
value: "users",
module: "loop"
}, {
type: "placeholder",
value: "rrr",
module: "rawxml"
}]);
});
});
describe("Change the delimiters", function () {
it("should work with lt and gt delimiter < and >", function () {
var doc = createDocV4("delimiter-gt.docx", {
delimiters: {
start: "<",
end: ">"
}
});
doc.render({
user: "John"
});
var fullText = doc.getFullText();
expect(fullText).to.be.equal("Hello John");
});
it("should work with delimiter % both sides", function () {
var doc = createDocV4("delimiter-pct.docx", {
delimiters: {
start: "%",
end: "%"
}
});
doc.render({
user: "John",
company: "PCorp"
});
var fullText = doc.getFullText();
expect(fullText).to.be.equal("Hello John from PCorp");
});
});
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 = createXmlTemplaterDocx(content, {
tags: scope
});
var c = getContent(xmlTemplater);
expect(c).to.be.deep.equal('<w:t xml:space="preserve">Hello Edgar</w:t>');
});
it("should not decode xml entities recursively", function () {
var content = "<w:t>Hello {&lt;}</w:t>";
var scope = {
"<": "good",
"<": "bad!!"
};
var xmlTemplater = createXmlTemplaterDocx(content, {
tags: scope
});
var c = getContent(xmlTemplater);
expect(c).to.be.deep.equal('<w:t xml:space="preserve">Hello good</w:t>');
});
it("should render placeholder containing special characters", function () {
var content = "<w:t>Hello {name}</w:t>";
var scope = {
name: "<Edgar>"
};
var xmlTemplater = createXmlTemplaterDocx(content, {
tags: scope
});
var c = getContent(xmlTemplater);
expect(c).to.be.deep.equal('<w:t xml:space="preserve">Hello <Edgar></w:t>');
});
it("should read full text correctly", function () {
var doc = createDocV4("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 = createDocV4("cyrillic.docx");
doc.render({
name: "Edgar"
});
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 russian = "Пупкина";
var doc = createDocV4("tag-example.docx");
doc.render({
last_name: russian
});
var outputText = doc.getFullText();
expect(outputText.substr(0, 7)).to.be.equal(russian);
});
});
describe("Complex table example", function () {
it("should not do anything special when loop outside of table", function () {
var content = "<w:p><w:t>{#tables}</w:t></w:p>\n<w:tbl><w:tr><w:tc>\n<w:p><w:t>{user}</w:t></w:p>\n</w:tc></w:tr></w:tbl>\n<w:p><w:t>{/tables}</w:t></w:p>";
var scope = {
tables: [{
user: "John"
}, {
user: "Jane"
}]
};
var doc = createXmlTemplaterDocx(content, {
tags: scope
});
var c = getContent(doc);
expect(c).to.be.equal("<w:p><w:t/></w:p>\n<w:tbl><w:tr><w:tc>\n<w:p><w:t xml:space=\"preserve\">John</w:t></w:p>\n</w:tc></w:tr></w:tbl>\n<w:p><w:t/></w:p>\n<w:tbl><w:tr><w:tc>\n<w:p><w:t xml:space=\"preserve\">Jane</w:t></w:p>\n</w:tc></w:tr></w:tbl>\n<w:p><w:t/></w:p>");
});
it("should work when looping inside tables", function () {
var tags = {
table1: [1],
key: "value"
};
var template = "<w:tr>\n\t\t<w:tc><w:p><w:t>{#table1}Hi</w:t></w:p></w:tc>\n\t\t<w:tc><w:p><w:t>{/table1}</w:t></w:p> </w:tc>\n\t\t</w:tr>\n\t\t<w:tr>\n\t\t<w:tc><w:p><w:t>{#table1}Ho</w:t></w:p></w:tc>\n\t\t<w:tc><w:p><w:t>{/table1}</w:t></w:p></w:tc>\n\t\t</w:tr>\n\t\t<w:p><w:t>{key}</w:t></w:p>\n\t\t";
var doc = createXmlTemplaterDocx(template, {
tags: tags
});
var fullText = doc.getFullText();
expect(fullText).to.be.equal("HiHovalue");
var expected = "<w:tr>\n\t\t<w:tc><w:p><w:t xml:space=\"preserve\">Hi</w:t></w:p></w:tc>\n\t\t<w:tc><w:p><w:t/></w:p> </w:tc>\n\t\t</w:tr>\n\t\t<w:tr>\n\t\t<w:tc><w:p><w:t xml:space=\"preserve\">Ho</w:t></w:p></w:tc>\n\t\t<w:tc><w:p><w:t/></w:p></w:tc>\n\t\t</w:tr>\n\t\t<w:p><w:t xml:space=\"preserve\">value</w:t></w:p>\n\t\t";
var c = getContent(doc);
expect(c).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>".concat(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 = createXmlTemplaterDocx(content, {
tags: scope
});
var c = getContent(doc);
expect(c.length).to.be.equal(content.length + scope.complexXml.length - inner.length + "<w:p/>".length);
expect(c).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 = createXmlTemplaterDocx(content, {
tags: scope
});
var c = getContent(doc);
expect(c).to.contain(scope.complexXml);
expect(doc.getFullText()).to.be.equal("HelloJohnDoe 1550MotoFein 1987WaterTest 2010BreadYu");
});
it("should work with false value", function () {
var content = "\n\t\t\t<w:p><w:r><w:t>{@rawXML}</w:t></w:r></w:p>\n\t\t\t<w:p><w:r><w:t>Hi</w:t></w:r></w:p>\n\t\t";
var doc = createXmlTemplaterDocx(content, {
tags: {
rawXML: false
}
});
expect(doc.getFullText()).to.be.equal("Hi");
});
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 = createXmlTemplaterDocx(content, {
tags: scope
});
var c = getContent(xmlTemplater);
expect(c).not.to.contain("</w:t></w:t>");
});
it("should work with simple example and given options", function () {
var doc = createDocV4("one-raw-xml-tag.docx", {
fileTypeConfig: assign({}, Docxtemplater.FileTypeConfig.docx(), {
tagRawXml: "w:r"
})
});
doc.render({
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>'
});
expect(doc.getFullText()).to.be.equal("asdfMy customXMLqwery");
});
});
describe("Multi line", function () {
it("should work when tag spans multiple lines (paragraphs)", function () {
return this.render({
name: "tag-spanning-multiline.docx",
data: {
first_name: "Hipp",
last_name: "Edgar",
phone: "0652455478",
description: "New Website"
},
expectedName: "expected-tag-spanning-multiline.docx"
});
});
});
describe("Constructor v4", function () {
it("should work when modules are attached", function () {
var isModuleCalled = false;
var module = {
name: "TestModule",
optionsTransformer: function optionsTransformer(options) {
isModuleCalled = true;
return options;
}
};
createDocV4("tag-example.docx", {
modules: [module]
});
expect(isModuleCalled).to.equal(true);
});
it("should throw an error when modules passed is not an array", function () {
expect(function () {
return new Docxtemplater(getZip("tag-example.docx"), {
modules: {}
});
}).to["throw"]("The modules argument of docxtemplater's constructor must be an array");
});
it("should throw an error when an invalid zip is passed", function () {
var zip = getZip("tag-example.docx");
zip.files = null;
expect(function () {
return new Docxtemplater(zip);
}).to["throw"]("The first argument of docxtemplater's constructor must be a valid zip file (jszip v2 or pizzip v3)");
expect(function () {
return new Docxtemplater("content");
}).to["throw"]("The first argument of docxtemplater's constructor must be a valid zip file (jszip v2 or pizzip v3)");
expect(function () {
return new Docxtemplater({
files: []
});
}).to["throw"]("The first argument of docxtemplater's constructor must be a valid zip file (jszip v2 or pizzip v3)");
if (typeof Buffer !== "undefined") {
expect(function () {
return new Docxtemplater(Buffer.from("content"));
}).to["throw"]("The first argument of docxtemplater's constructor must be a valid zip file (jszip v2 or pizzip v3)");
}
});
it("should work when the delimiters are passed", function () {
var options = {
delimiters: {
start: "<",
end: ">"
}
};
var doc = createDocV4("delimiter-gt.docx", options);
doc.render({
user: "John"
});
var fullText = doc.getFullText();
expect(fullText).to.be.equal("Hello John");
});
it("should work when both modules and delimiters are passed and modules should have access to options object", function () {
var isModuleCalled = false,
optionsPassedToModule;
var options = {
delimiters: {
start: "%",
end: "%"
},
modules: [{
name: "MyModule",
optionsTransformer: function optionsTransformer(options) {
optionsPassedToModule = options;
isModuleCalled = true;
return options;
}
}]
};
var doc = createDocV4("delimiter-pct.docx", options);
expect(isModuleCalled).to.be.equal(true);
expect(optionsPassedToModule.delimiters.start).to.be.equal("%");
expect(optionsPassedToModule.delimiters.end).to.be.equal("%");
// Verify that default options are passed to the modules
expect(optionsPassedToModule.linebreaks).to.be.equal(false);
doc.render({
user: "John",
company: "Acme"
});
var fullText = doc.getFullText();
expect(fullText).to.be.equal("Hello John from Acme");
});
var MyTestModule = /*#__PURE__*/function () {
function MyTestModule() {
_classCallCheck(this, MyTestModule);
}
return _createClass(MyTestModule, [{
key: "render",
value: function render(part) {
return {
value: part.value
};
}
}]);
}();
it("should throw error when using a non-instanciated class as a module", function () {
var options = {
delimiters: {
start: "%",
end: "%"
},
modules: [MyTestModule]
};
expect(function () {
return createDocV4("delimiter-pct.docx", options);
}).to["throw"]("Cannot attach a class/function as a module. Most probably you forgot to instantiate the module by using `new` on the module.");
});
it("should throw if using v4 constructor and setOptions", function () {
var doc = createDocV4("tag-multiline.docx");
expect(function () {
return doc.setOptions({
linebreaks: true
});
}).to["throw"]("setOptions() should not be called manually when using the v4 constructor");
});
it("should throw if using v4 constructor and attachModule", function () {
var doc = createDocV4("tag-multiline.docx");
expect(function () {
return doc.attachModule({
render: function render() {}
});
}).to["throw"]("attachModule() should not be called manually when using the v4 constructor");
});
it("should throw if using v4 constructor and loadZip", function () {
var doc = createDocV4("tag-multiline.docx");
expect(function () {
return doc.loadZip();
}).to["throw"]("loadZip() should not be called manually when using the v4 constructor");
});
it("should render correctly", function () {
var doc = new Docxtemplater(getZip("tag-example.docx"));
doc.render({
first_name: "John",
last_name: "Doe"
});
expect(doc.getFullText()).to.be.equal("Doe John");
});
it("should work when modules are attached with valid filetypes", function () {
var isModuleCalled = false;
var module = {
name: "FooModule",
optionsTransformer: function optionsTransformer(options) {
isModuleCalled = true;
return options;
},
supportedFileTypes: ["pptx", "docx"]
};
createDocV4("tag-example.docx", {
modules: [module]
});
expect(isModuleCalled).to.equal(true);
});
it("should throw an error when supportedFieldType property in passed module is not an Array", function () {
var zip = getZip("tag-example.docx");
var module = {
optionsTransformer: function optionsTransformer(options) {
return options;
},
supportedFileTypes: "pptx"
};
expect(function () {
return new Docxtemplater(zip, {
modules: [module]
});
}).to["throw"]("The supportedFileTypes field of the module must be an array");
});
it("should fail with readable error when using new Docxtemplater(null)", function () {
expect(function () {
return new Docxtemplater(null, {});
}).to["throw"]("The first argument of docxtemplater's constructor must be a valid zip file (jszip v2 or pizzip v3)");
});
it("should fail with readable error when using new Docxtemplater(null, {modules: [inspectModule()]})", function () {
expect(function () {
return new Docxtemplater(null, {
modules: [inspectModule()]
});
}).to["throw"]("The first argument of docxtemplater's constructor must be a valid zip file (jszip v2 or pizzip v3)");
});
});