docxtemplater
Version:
.docx generator working with templates and data (like Mustache)
1,655 lines (1,479 loc) • 452 kB
JavaScript
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
"use strict";
/* eslint-disable no-var */
var Docxtemplater = require("../js/docxtemplater.js");
window.Docxtemplater = Docxtemplater;
var expressions = require("angular-expressions");
var JSZip = require("jszip");
window.expressions = expressions;
function textAreaAdjust(o) {
o.style.height = "1px";
o.style.height = (25 + o.scrollHeight) + "px";
}
function loadFile(url, callback) {
JSZipUtils.getBinaryContent(url, function (err, data) {
callback(err, data);
});
}
window.onload = function () {
var i;
var textAreaList = document.getElementsByTagName("textarea");
for (i = textAreaList.length - 1; i >= 0; i--) {
textAreaAdjust(textAreaList[i]);
var executeButton = document.createElement("button");
executeButton.className = "execute";
executeButton.innerHTML = "Execute";
textAreaList[i].parentNode.insertBefore(executeButton, textAreaList[i].nextSibling);
var viewRawButton = document.createElement("button");
viewRawButton.className = "raw";
viewRawButton.innerHTML = "View Initial Document";
textAreaList[i].parentNode.insertBefore(viewRawButton, textAreaList[i].nextSibling);
}
var executeButtonList = document.getElementsByClassName("execute");
function executeFn() {
var childs = (this.parentNode.childNodes);
for (var j = 0; j < childs.length; j++) {
if (childs[j].tagName === "TEXTAREA") {
/* eslint-disable no-eval */
eval(childs[j].value);
}
}
}
for (i = 0; i < executeButtonList.length; i++) {
executeButtonList[i].onclick = executeFn;
}
var viewRawButtonList = document.getElementsByClassName("raw");
function saveAsRaw(err, content) {
if (err) {
throw err;
}
var zip = new JSZip(content);
var output = new Docxtemplater().loadZip(zip).getZip().generate({type: "blob"});
saveAs(output, "raw.docx");
}
function viewRawFn() {
var childs = (this.parentNode.childNodes);
for (var j = 0; j < childs.length; j++) {
if (childs[j].tagName === "TEXTAREA") {
var raw = (childs[j].getAttribute("raw"));
loadFile(raw, saveAsRaw);
}
}
}
for (i = 0; i < viewRawButtonList.length; i++) {
viewRawButtonList[i].onclick = viewRawFn;
}
};
},{"../js/docxtemplater.js":3,"angular-expressions":21,"jszip":32}],2:[function(require,module,exports){
"use strict";
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 memoize = require("./memoize");
var DOMParser = require("xmldom").DOMParser;
var XMLSerializer = require("xmldom").XMLSerializer;
var Errors = require("./errors");
var DocUtils = {};
function parser(tag) {
return _defineProperty({}, "get", function get(scope) {
if (tag === ".") {
return scope;
}
return scope[tag];
});
}
DocUtils.defaults = {
nullGetter: function nullGetter(part) {
if (!part.module) {
return "undefined";
}
if (part.module === "rawxml") {
return "";
}
return "";
},
parser: memoize(parser),
delimiters: {
start: "{",
end: "}"
}
};
DocUtils.mergeObjects = function () {
var resObj = {};
var obj = void 0,
keys = void 0;
for (var i = 0; i < arguments.length; i += 1) {
obj = arguments[i];
keys = Object.keys(obj);
for (var j = 0; j < keys.length; j += 1) {
resObj[keys[j]] = obj[keys[j]];
}
}
return resObj;
};
DocUtils.xml2str = function (xmlNode) {
var a = new XMLSerializer();
return a.serializeToString(xmlNode);
};
DocUtils.decodeUtf8 = function (s) {
try {
if (s === undefined) {
return undefined;
}
// replace Ascii 160 space by the normal space, Ascii 32
return decodeURIComponent(escape(DocUtils.convertSpaces(s)));
} catch (e) {
var err = new Error("End");
err.properties.data = s;
err.properties.explanation = "Could not decode string to UTF8";
throw err;
}
};
DocUtils.encodeUtf8 = function (s) {
return unescape(encodeURIComponent(s));
};
DocUtils.str2xml = function (str, errorHandler) {
var parser = new DOMParser({ errorHandler: errorHandler });
return parser.parseFromString(str, "text/xml");
};
DocUtils.charMap = {
"&": "&",
"'": "'",
"<": "<",
">": ">"
};
var regexStripRegexp = /[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g;
DocUtils.escapeRegExp = function (str) {
return str.replace(regexStripRegexp, "\\$&");
};
DocUtils.charMapRegexes = Object.keys(DocUtils.charMap).map(function (endChar) {
var startChar = DocUtils.charMap[endChar];
return {
rstart: new RegExp(DocUtils.escapeRegExp(startChar), "g"),
rend: new RegExp(DocUtils.escapeRegExp(endChar), "g"),
start: startChar,
end: endChar
};
});
DocUtils.wordToUtf8 = function (string) {
var r = void 0;
for (var i = 0, l = DocUtils.charMapRegexes.length; i < l; i++) {
r = DocUtils.charMapRegexes[i];
string = string.replace(r.rstart, r.end);
}
return string;
};
DocUtils.utf8ToWord = function (string) {
if (typeof string !== "string") {
string = string.toString();
}
var r = void 0;
for (var i = 0, l = DocUtils.charMapRegexes.length; i < l; i++) {
r = DocUtils.charMapRegexes[i];
string = string.replace(r.rend, r.start);
}
return string;
};
DocUtils.cloneDeep = function (obj) {
return JSON.parse(JSON.stringify(obj));
};
DocUtils.concatArrays = function (arrays) {
return arrays.reduce(function (result, array) {
Array.prototype.push.apply(result, array);
return result;
}, []);
};
var spaceRegexp = new RegExp(String.fromCharCode(160), "g");
DocUtils.convertSpaces = function (s) {
return s.replace(spaceRegexp, " ");
};
DocUtils.pregMatchAll = function (regex, content) {
/* regex is a string, content is the content. It returns an array of all matches with their offset, for example:
regex=la
content=lolalolilala
returns: [{array: {0: 'la'},offset: 2},{array: {0: 'la'},offset: 8},{array: {0: 'la'} ,offset: 10}]
*/
var matchArray = [];
var match = void 0;
while ((match = regex.exec(content)) != null) {
matchArray.push({ array: match, offset: match.index });
}
return matchArray;
};
DocUtils.sizeOfObject = function (obj) {
return Object.keys(obj).length;
};
function throwXmlTagNotFound(options) {
var err = new Errors.XTTemplateError("No tag '" + options.element + "' was found at the " + options.position);
err.properties = {
id: "no_xml_tag_found_at_" + options.position,
explanation: "No tag '" + options.element + "' was found at the " + options.position,
parsed: options.parsed,
index: options.index,
element: options.element
};
throw err;
}
DocUtils.getRight = function (parsed, element, index) {
for (var i = index, l = parsed.length; i < l; i++) {
var part = parsed[i];
if (part.value === "</" + element + ">") {
return i;
}
}
throwXmlTagNotFound({ position: "right", element: element, parsed: parsed, index: index });
};
DocUtils.getLeft = function (parsed, element, index) {
for (var i = index; i >= 0; i--) {
var part = parsed[i];
if (part.value.indexOf("<" + element) === 0 && [">", " "].indexOf(part.value[element.length + 1]) !== -1) {
return i;
}
}
throwXmlTagNotFound({ position: "left", element: element, parsed: parsed, index: index });
};
module.exports = DocUtils;
},{"./errors":4,"./memoize":7,"xmldom":63}],3:[function(require,module,exports){
"use strict";
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var DocUtils = require("./doc-utils");
DocUtils.traits = require("./traits");
DocUtils.moduleWrapper = require("./module-wrapper");
var wrapper = DocUtils.moduleWrapper;
var Docxtemplater = function () {
function Docxtemplater() {
_classCallCheck(this, Docxtemplater);
if (arguments.length > 0) {
throw new Error("The constructor with parameters have been removed in docxtemplater 3.0, please check the upgrade guide.");
}
this.compiled = {};
this.modules = [];
this.setOptions({});
}
_createClass(Docxtemplater, [{
key: "attachModule",
value: function attachModule(module) {
this.modules.push(wrapper(module));
return this;
}
}, {
key: "setOptions",
value: function setOptions(options) {
var _this = this;
this.options = options;
Object.keys(DocUtils.defaults).forEach(function (key) {
var defaultValue = DocUtils.defaults[key];
_this[key] = _this.options[key] != null ? _this.options[key] : defaultValue;
});
if (this.zip) {
this.updateFileTypeConfig();
}
return this;
}
}, {
key: "loadZip",
value: function loadZip(zip) {
if (zip.loadAsync) {
throw new Error("Docxtemplater doesn't handle JSZip version >=3, see changelog");
}
this.zip = zip;
this.updateFileTypeConfig();
return this;
}
}, {
key: "compileFile",
value: function compileFile(fileName) {
var currentFile = this.createTemplateClass(fileName);
currentFile.parse();
this.compiled[fileName] = currentFile;
}
}, {
key: "compile",
value: function compile() {
this.templatedFiles = this.fileTypeConfig.getTemplatedFiles(this.zip);
return this;
}
}, {
key: "updateFileTypeConfig",
value: function updateFileTypeConfig() {
this.fileType = this.zip.files["word/document.xml"] ? "docx" : "pptx";
this.fileTypeConfig = this.options.fileTypeConfig || Docxtemplater.FileTypeConfig[this.fileType];
return this;
}
}, {
key: "render",
value: function render() {
var _this2 = this;
this.options.xmlFileNames = [];
this.modules = this.fileTypeConfig.baseModules.map(function (moduleFunction) {
return moduleFunction();
}).concat(this.modules);
this.options = this.modules.reduce(function (options, module) {
return module.optionsTransformer(options, _this2);
}, this.options);
this.xmlDocuments = this.options.xmlFileNames.reduce(function (xmlDocuments, fileName) {
var content = _this2.zip.files[fileName].asText();
xmlDocuments[fileName] = DocUtils.str2xml(content);
return xmlDocuments;
}, {});
this.modules.forEach(function (module) {
module.set({ zip: _this2.zip, xmlDocuments: _this2.xmlDocuments, data: _this2.data });
});
this.compile();
this.modules.forEach(function (module) {
module.set({ compiled: _this2.compiled });
});
// Loop inside all templatedFiles (ie xml files with content).
// Sometimes they don't exist (footer.xml for example)
this.templatedFiles.forEach(function (fileName) {
if (_this2.zip.files[fileName] != null) {
_this2.compileFile(fileName);
}
});
this.mapper = this.modules.reduce(function (value, module) {
return module.getRenderedMap(value);
}, {});
Object.keys(this.mapper).forEach(function (to) {
var mapped = _this2.mapper[to];
var from = mapped.from;
var currentFile = _this2.compiled[from];
currentFile.setTags(mapped.data);
currentFile.render(to);
_this2.zip.file(to, currentFile.content);
});
Object.keys(this.xmlDocuments).forEach(function (fileName) {
_this2.zip.remove(fileName);
var content = DocUtils.xml2str(_this2.xmlDocuments[fileName]);
return _this2.zip.file(fileName, content, {});
});
return this;
}
}, {
key: "setData",
value: function setData(data) {
this.data = data;
return this;
}
}, {
key: "getZip",
value: function getZip() {
return this.zip;
}
}, {
key: "createTemplateClass",
value: function createTemplateClass(path) {
var usedData = this.zip.files[path].asText();
return this.createTemplateClassFromContent(usedData, path);
}
}, {
key: "createTemplateClassFromContent",
value: function createTemplateClassFromContent(content, filePath) {
var _this3 = this;
var xmltOptions = {
filePath: filePath
};
Object.keys(DocUtils.defaults).forEach(function (key) {
xmltOptions[key] = _this3[key];
});
xmltOptions.fileTypeConfig = this.fileTypeConfig;
xmltOptions.modules = this.modules;
return new Docxtemplater.XmlTemplater(content, xmltOptions);
}
}, {
key: "getFullText",
value: function getFullText(path) {
return this.createTemplateClass(path || this.fileTypeConfig.textPath).getFullText();
}
}, {
key: "getTemplatedFiles",
value: function getTemplatedFiles() {
this.compile();
return this.templatedFiles;
}
}]);
return Docxtemplater;
}();
Docxtemplater.DocUtils = require("./doc-utils");
Docxtemplater.Errors = require("./errors");
Docxtemplater.XmlTemplater = require("./xml-templater");
Docxtemplater.FileTypeConfig = require("./file-type-config");
Docxtemplater.XmlMatcher = require("./xml-matcher");
module.exports = Docxtemplater;
},{"./doc-utils":2,"./errors":4,"./file-type-config":5,"./module-wrapper":9,"./traits":18,"./xml-matcher":19,"./xml-templater":20}],4:[function(require,module,exports){
"use strict";
function XTError(message) {
this.name = "GenericError";
this.message = message;
this.stack = new Error(message).stack;
}
XTError.prototype = Error.prototype;
function XTTemplateError(message) {
this.name = "TemplateError";
this.message = message;
this.stack = new Error(message).stack;
}
XTTemplateError.prototype = new XTError();
function XTScopeParserError(message) {
this.name = "ScopeParserError";
this.message = message;
this.stack = new Error(message).stack;
}
XTScopeParserError.prototype = new XTError();
function XTInternalError(message) {
this.name = "InternalError";
this.properties = { explanation: "InternalError" };
this.message = message;
this.stack = new Error(message).stack;
}
XTInternalError.prototype = new XTError();
module.exports = {
XTError: XTError,
XTTemplateError: XTTemplateError,
XTInternalError: XTInternalError,
XTScopeParserError: XTScopeParserError
};
},{}],5:[function(require,module,exports){
"use strict";
var loopModule = require("./modules/loop");
var spacePreserveModule = require("./modules/space-preserve");
var rawXmlModule = require("./modules/rawxml");
var expandPairTrait = require("./modules/expand-pair-trait");
var render = require("./modules/render");
var PptXFileTypeConfig = {
getTemplatedFiles: function getTemplatedFiles(zip) {
var slideTemplates = zip.file(/ppt\/(slides|slideMasters)\/(slide|slideMaster)\d+\.xml/).map(function (file) {
return file.name;
});
return slideTemplates.concat(["ppt/presentation.xml"]);
},
textPath: "ppt/slides/slide1.xml",
tagsXmlTextArray: ["a:t", "m:t"],
tagsXmlLexedArray: ["p:sp", "a:tc", "a:tr", "a:table", "a:p", "a:r"],
tagRawXml: "p:sp",
tagTextXml: "a:t",
baseModules: [render, expandPairTrait, rawXmlModule, loopModule]
};
var DocXFileTypeConfig = {
getTemplatedFiles: function getTemplatedFiles(zip) {
var slideTemplates = zip.file(/word\/(header|footer)\d+\.xml/).map(function (file) {
return file.name;
});
return slideTemplates.concat(["word/document.xml"]);
},
textPath: "word/document.xml",
tagsXmlTextArray: ["w:t", "m:t"],
tagsXmlLexedArray: ["w:tc", "w:tr", "w:table", "w:p", "w:r"],
tagRawXml: "w:p",
tagTextXml: "w:t",
baseModules: [render, spacePreserveModule, expandPairTrait, rawXmlModule, loopModule]
};
module.exports = {
docx: DocXFileTypeConfig,
pptx: PptXFileTypeConfig
};
},{"./modules/expand-pair-trait":10,"./modules/loop":11,"./modules/rawxml":12,"./modules/render":13,"./modules/space-preserve":14}],6:[function(require,module,exports){
"use strict";
var Errors = require("./errors");
var DocUtils = require("./doc-utils");
function inRange(range, match) {
return range[0] <= match.offset && match.offset < range[1];
}
function updateInTextTag(part, inTextTag) {
if (part.type === "tag" && part.position === "start" && part.text) {
if (inTextTag) {
throw new Error("Malformed xml : Already in text tag");
}
return true;
}
if (part.type === "tag" && part.position === "end" && part.text) {
if (!inTextTag) {
throw new Error("Malformed xml : Already not in text tag");
}
return false;
}
return inTextTag;
}
function offsetSort(a, b) {
return a.offset - b.offset;
}
function getTag(tag) {
var start = 1;
if (tag[1] === "/") {
start = 2;
}
var index = tag.indexOf(" ");
var end = index === -1 ? tag.length - 1 : index;
return {
tag: tag.slice(start, end),
position: start === 1 ? "start" : "end"
};
}
function tagMatcher(content, textMatchArray, othersMatchArray) {
var cursor = 0;
var contentLength = content.length;
var allMatches = DocUtils.concatArrays([textMatchArray.map(function (tag) {
return { tag: tag, text: true };
}), othersMatchArray.map(function (tag) {
return { tag: tag, text: false };
})]).reduce(function (allMatches, t) {
allMatches[t.tag] = t.text;
return allMatches;
}, {});
var totalMatches = [];
while (cursor < contentLength) {
cursor = content.indexOf("<", cursor);
if (cursor === -1) {
break;
}
var offset = cursor;
cursor = content.indexOf(">", cursor);
var tagText = content.slice(offset, cursor + 1);
var _getTag = getTag(tagText),
tag = _getTag.tag,
position = _getTag.position;
var text = allMatches[tag];
if (text == null) {
continue;
}
totalMatches.push({ type: "tag", position: position, text: text, offset: offset, value: tagText });
}
return totalMatches;
}
function throwUnopenedTagException(options) {
var err = new Errors.XTTemplateError("Unopened tag");
err.properties = {
xtag: options.xtag.split(" ")[0],
id: "unopened_tag",
context: options.xtag,
explanation: "The tag beginning with '" + options.xtag.substr(0, 10) + "' is unclosed"
};
throw err;
}
function throwUnclosedTagException(options) {
var err = new Errors.XTTemplateError("Unclosed tag");
err.properties = {
xtag: options.xtag.split(" ")[0].substr(1),
id: "unclosed_tag",
context: options.xtag,
explanation: "The tag beginning with '" + options.xtag.substr(0, 10) + "' is unclosed"
};
throw err;
}
function assertDelimiterOrdered(delimiterMatches, fullText) {
var inDelimiter = false;
var lastDelimiterMatch = { offset: 0 };
var xtag = void 0;
delimiterMatches.forEach(function (delimiterMatch) {
xtag = fullText.substr(lastDelimiterMatch.offset, delimiterMatch.offset - lastDelimiterMatch.offset);
if (delimiterMatch.position === "start" && inDelimiter || delimiterMatch.position === "end" && !inDelimiter) {
if (delimiterMatch.position === "start") {
throwUnclosedTagException({ xtag: xtag });
} else {
throwUnopenedTagException({ xtag: xtag });
}
}
inDelimiter = !inDelimiter;
lastDelimiterMatch = delimiterMatch;
});
var delimiterMatch = { offset: fullText.length };
xtag = fullText.substr(lastDelimiterMatch.offset, delimiterMatch.offset - lastDelimiterMatch.offset);
if (inDelimiter) {
throwUnclosedTagException({ xtag: xtag });
}
}
function getAllIndexes(arr, val, position) {
var indexes = [];
var offset = -1;
do {
offset = arr.indexOf(val, offset + 1);
if (offset !== -1) {
indexes.push({ offset: offset, position: position });
}
} while (offset !== -1);
return indexes;
}
function Reader(innerContentParts) {
var _this = this;
this.innerContentParts = innerContentParts;
this.full = "";
this.parseDelimiters = function (delimiters) {
_this.full = _this.innerContentParts.join("");
var offset = 0;
_this.ranges = _this.innerContentParts.map(function (part) {
offset += part.length;
return offset - part.length;
});
var delimiterMatches = DocUtils.concatArrays([getAllIndexes(_this.full, delimiters.start, "start"), getAllIndexes(_this.full, delimiters.end, "end")]).sort(offsetSort);
assertDelimiterOrdered(delimiterMatches, _this.full);
var delimiterLength = { start: delimiters.start.length, end: delimiters.end.length };
var cutNext = 0;
var delimiterIndex = 0;
_this.parsed = _this.ranges.map(function (offset, i) {
var range = [offset, offset + this.innerContentParts[i].length];
var partContent = this.innerContentParts[i];
var delimitersInOffset = [];
while (delimiterIndex < delimiterMatches.length && inRange(range, delimiterMatches[delimiterIndex])) {
delimitersInOffset.push(delimiterMatches[delimiterIndex]);
delimiterIndex++;
}
var parts = [];
var cursor = 0;
if (cutNext > 0) {
cursor = cutNext;
cutNext = 0;
}
delimitersInOffset.forEach(function (delimiterInOffset) {
var value = partContent.substr(cursor, delimiterInOffset.offset - offset - cursor);
if (value.length > 0) {
parts.push({ type: "content", value: value });
}
parts.push({ type: "delimiter", position: delimiterInOffset.position });
cursor = delimiterInOffset.offset - offset + delimiterLength[delimiterInOffset.position];
});
cutNext = cursor - partContent.length;
var value = partContent.substr(cursor);
if (value.length > 0) {
parts.push({ type: "content", value: value });
}
return parts;
}, _this);
};
}
module.exports = {
parse: function parse(xmlparsed, delimiters) {
var inTextTag = false;
var innerContentParts = [];
xmlparsed.forEach(function (part) {
inTextTag = updateInTextTag(part, inTextTag);
if (inTextTag && part.type === "content") {
innerContentParts.push(part.value);
}
});
var reader = new Reader(innerContentParts);
reader.parseDelimiters(delimiters);
var newArray = [];
var index = 0;
xmlparsed.forEach(function (part) {
inTextTag = updateInTextTag(part, inTextTag);
if (part.type === "content") {
part.position = inTextTag ? "insidetag" : "outsidetag";
}
if (inTextTag && part.type === "content") {
Array.prototype.push.apply(newArray, reader.parsed[index].map(function (p) {
if (p.type === "content") {
p.position = "insidetag";
}
return p;
}));
index++;
} else {
newArray.push(part);
}
});
return newArray;
},
xmlparse: function xmlparse(content, xmltags) {
var matches = tagMatcher(content, xmltags.text, xmltags.other);
var cursor = 0;
var parsed = matches.reduce(function (parsed, match) {
var value = content.substr(cursor, match.offset - cursor);
if (value.length > 0) {
parsed.push({ type: "content", value: value });
}
cursor = match.offset + match.value.length;
delete match.offset;
if (match.value.length > 0) {
parsed.push(match);
}
return parsed;
}, []);
var value = content.substr(cursor);
if (value.length > 0) {
parsed.push({ type: "content", value: value });
}
return parsed;
}
};
},{"./doc-utils":2,"./errors":4}],7:[function(require,module,exports){
"use strict";
function memoize(func) {
var stringifyJson = JSON.stringify,
cache = {};
function cachedfun() {
var hash = stringifyJson(arguments);
return hash in cache ? cache[hash] : cache[hash] = func.apply(this, arguments);
}
return cachedfun;
}
module.exports = memoize;
},{}],8:[function(require,module,exports){
"use strict";
function getMinFromArrays(arrays, state) {
var minIndex = -1;
for (var i = 0, l = arrays.length; i < l; i++) {
if (state[i] >= arrays[i].length) {
continue;
}
if (minIndex === -1 || arrays[i][state[i]].offset < arrays[minIndex][state[minIndex]].offset) {
minIndex = i;
}
}
if (minIndex === -1) {
throw new Error("minIndex negative");
}
return minIndex;
}
module.exports = function (arrays) {
var totalLength = arrays.reduce(function (sum, array) {
return sum + array.length;
}, 0);
arrays = arrays.filter(function (array) {
return array.length > 0;
});
var resultArray = new Array(totalLength);
var state = arrays.map(function () {
return 0;
});
var i = 0;
while (i <= totalLength - 1) {
var arrayIndex = getMinFromArrays(arrays, state);
resultArray[i] = arrays[arrayIndex][state[arrayIndex]];
state[arrayIndex]++;
i++;
}
return resultArray;
};
},{}],9:[function(require,module,exports){
"use strict";
function emptyFun() {}
function identity(i) {
return i;
}
module.exports = function (module) {
var defaults = {
set: emptyFun,
parse: emptyFun,
render: emptyFun,
getTraits: emptyFun,
optionsTransformer: identity,
getRenderedMap: identity,
postparse: identity
};
if (Object.keys(defaults).every(function (key) {
return !module[key];
})) {
throw new Error("This module cannot be wrapped, because it doesn't define any of the necessary functions");
}
Object.keys(defaults).forEach(function (key) {
module[key] = module[key] || defaults[key];
});
return module;
};
},{}],10:[function(require,module,exports){
"use strict";
var traitName = "expandPair";
var mergeSort = require("../mergesort");
var DocUtils = require("../doc-utils");
var wrapper = require("../module-wrapper");
var _require = require("../traits"),
getExpandToDefault = _require.getExpandToDefault;
var Errors = require("../errors");
function throwUnmatchedLoopException(options) {
var location = options.location;
var t = location === "start" ? "unclosed" : "unopened";
var T = location === "start" ? "Unclosed" : "Unopened";
var err = new Errors.XTTemplateError(T + " loop");
var tag = options.part.value;
err.properties = {
id: t + "_loop",
explanation: "The loop with tag " + tag + " is " + t,
xtag: tag
};
throw err;
}
function throwClosingTagNotMatchOpeningTag(options) {
var tags = options.tags;
var err = new Errors.XTTemplateError("Closing tag does not match opening tag");
err.properties = {
id: "closing_tag_does_not_match_opening_tag",
explanation: "The tag \"" + tags[0].value + "\" is closed by the tag \"" + tags[1].value + "\"",
openingtag: tags[0].value,
closingtag: tags[1].value
};
throw err;
}
function getOpenCountChange(part) {
switch (part.location) {
case "start":
return 1;
case "end":
return -1;
default:
throw new Error("Location should be one of 'start' or 'end' (given : " + part.location + ")");
}
}
function getPairs(traits) {
if (traits.length === 0) {
return [];
}
var countOpen = 1;
var firstTrait = traits[0];
for (var i = 1; i < traits.length; i++) {
var currentTrait = traits[i];
countOpen += getOpenCountChange(currentTrait.part);
if (countOpen === 0) {
if (currentTrait.part.value !== firstTrait.part.value && currentTrait.part.value !== "") {
throwClosingTagNotMatchOpeningTag({ tags: [firstTrait.part, currentTrait.part] });
}
var outer = getPairs(traits.slice(i + 1));
return [[firstTrait, currentTrait]].concat(outer);
}
}
var part = firstTrait.part;
throwUnmatchedLoopException({ part: part, location: part.location });
}
var expandPairTrait = {
name: "ExpandPairTrait",
postparse: function postparse(parsed, _ref) {
var getTraits = _ref.getTraits,
_postparse = _ref.postparse;
var traits = getTraits(traitName, parsed);
traits = traits.map(function (trait) {
return trait || [];
});
traits = mergeSort(traits);
var pairs = getPairs(traits);
var expandedPairs = pairs.map(function (pair) {
var expandTo = pair[0].part.expandTo;
if (expandTo === "auto") {
expandTo = getExpandToDefault(parsed.slice(pair[0].offset, pair[1].offset));
}
if (!expandTo) {
return [pair[0].offset, pair[1].offset];
}
var left = DocUtils.getLeft(parsed, expandTo, pair[0].offset);
var right = DocUtils.getRight(parsed, expandTo, pair[1].offset);
return [left, right];
});
var currentPairIndex = 0;
var innerParts = void 0;
return parsed.reduce(function (newParsed, part, i) {
var inPair = currentPairIndex < pairs.length && expandedPairs[currentPairIndex][0] <= i;
var pair = pairs[currentPairIndex];
var expandedPair = expandedPairs[currentPairIndex];
if (!inPair) {
newParsed.push(part);
return newParsed;
}
if (expandedPair[0] === i) {
innerParts = [];
}
if (pair[0].offset !== i && pair[1].offset !== i) {
innerParts.push(part);
}
if (expandedPair[1] === i) {
var basePart = parsed[pair[0].offset];
delete basePart.location;
delete basePart.expandTo;
basePart.subparsed = _postparse(innerParts);
newParsed.push(basePart);
currentPairIndex++;
}
return newParsed;
}, []);
}
};
module.exports = function () {
return wrapper(expandPairTrait);
};
},{"../doc-utils":2,"../errors":4,"../mergesort":8,"../module-wrapper":9,"../traits":18}],11:[function(require,module,exports){
"use strict";
var DocUtils = require("../doc-utils");
var dashInnerRegex = /^-([^\s]+)\s(.+)$/;
var wrapper = require("../module-wrapper");
var moduleName = "loop";
var loopModule = {
name: "LoopModule",
parse: function parse(placeHolderContent) {
var module = moduleName;
var type = "placeholder";
if (placeHolderContent[0] === "#") {
return { type: type, value: placeHolderContent.substr(1), expandTo: "auto", module: module, location: "start", inverted: false };
}
if (placeHolderContent[0] === "^") {
return { type: type, value: placeHolderContent.substr(1), expandTo: "auto", module: module, location: "start", inverted: true };
}
if (placeHolderContent[0] === "/") {
return { type: type, value: placeHolderContent.substr(1), module: module, location: "end" };
}
if (placeHolderContent[0] === "-") {
var value = placeHolderContent.replace(dashInnerRegex, "$2");
var expandTo = placeHolderContent.replace(dashInnerRegex, "$1");
return { type: type, value: value, expandTo: expandTo, module: module, location: "start", inverted: false };
}
return null;
},
getTraits: function getTraits(traitName, parsed) {
if (traitName !== "expandPair") {
return;
}
return parsed.reduce(function (tags, part, offset) {
if (part.type === "placeholder" && part.module === moduleName) {
tags.push({ part: part, offset: offset });
}
return tags;
}, []);
},
render: function render(part, options) {
if (!part.type === "placeholder" || part.module !== moduleName) {
return null;
}
var totalValue = [];
function loopOver(scope) {
var scopeManager = options.scopeManager.createSubScopeManager(scope, part.value);
totalValue.push(options.render(DocUtils.mergeObjects({}, options, {
compiled: part.subparsed,
tags: {},
scopeManager: scopeManager
})));
}
options.scopeManager.loopOver(part.value, loopOver, part.inverted);
return { value: totalValue.join("") };
}
};
module.exports = function () {
return wrapper(loopModule);
};
},{"../doc-utils":2,"../module-wrapper":9}],12:[function(require,module,exports){
"use strict";
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var DocUtils = require("../doc-utils");
var Errors = require("../errors");
var moduleName = "rawxml";
var wrapper = require("../module-wrapper");
function throwRawTagShouldBeOnlyTextInParagraph(options) {
var err = new Errors.XTTemplateError("Raw tag should be the only text in paragraph");
var tag = options.part.value;
err.properties = {
id: "raw_xml_tag_should_be_only_text_in_paragraph",
explanation: "The tag " + tag,
xtag: options.part.value,
paragraphParts: options.paragraphParts
};
throw err;
}
function getInner(_ref) {
var part = _ref.part,
left = _ref.left,
right = _ref.right,
postparsed = _ref.postparsed,
index = _ref.index;
var paragraphParts = postparsed.slice(left + 1, right);
paragraphParts.forEach(function (p, i) {
if (i === index - left - 1) {
return;
}
if (p.type === "placeholder" || p.type === "content" && p.position === "insidetag") {
throwRawTagShouldBeOnlyTextInParagraph({ paragraphParts: paragraphParts, part: part });
}
});
return part;
}
var RawXmlModule = function () {
function RawXmlModule() {
_classCallCheck(this, RawXmlModule);
this.name = "RawXmlModule";
}
_createClass(RawXmlModule, [{
key: "optionsTransformer",
value: function optionsTransformer(options, docxtemplater) {
this.fileTypeConfig = docxtemplater.fileTypeConfig;
return options;
}
}, {
key: "parse",
value: function parse(placeHolderContent) {
var type = "placeholder";
if (placeHolderContent[0] !== "@") {
return null;
}
return { type: type, value: placeHolderContent.substr(1), module: moduleName };
}
}, {
key: "postparse",
value: function postparse(parsed) {
return DocUtils.traits.expandToOne(parsed, { moduleName: moduleName, getInner: getInner, expandTo: this.fileTypeConfig.tagRawXml });
}
}, {
key: "render",
value: function render(part, options) {
if (part.module !== moduleName) {
return null;
}
var value = options.scopeManager.getValue(part.value);
if (value == null) {
value = options.nullGetter(part);
}
return { value: value };
}
}]);
return RawXmlModule;
}();
module.exports = function () {
return wrapper(new RawXmlModule());
};
},{"../doc-utils":2,"../errors":4,"../module-wrapper":9}],13:[function(require,module,exports){
"use strict";
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var wrapper = require("../module-wrapper");
var Render = function () {
function Render() {
_classCallCheck(this, Render);
this.name = "Render";
}
_createClass(Render, [{
key: "set",
value: function set(obj) {
if (obj.compiled) {
this.compiled = obj.compiled;
}
if (obj.data != null) {
this.data = obj.data;
}
}
}, {
key: "getRenderedMap",
value: function getRenderedMap(mapper) {
var _this = this;
return Object.keys(this.compiled).reduce(function (mapper, from) {
mapper[from] = { from: from, data: _this.data };
return mapper;
}, mapper);
}
}]);
return Render;
}();
module.exports = function () {
return wrapper(new Render());
};
},{"../module-wrapper":9}],14:[function(require,module,exports){
"use strict";
var wrapper = require("../module-wrapper");
var spacePreserve = {
name: "SpacePreserveModule",
postparse: function postparse(parsed) {
var chunk = [];
var inChunk = false;
var result = parsed.reduce(function (parsed, part) {
if (part.type === "tag" && part.position === "start" && part.text && part.value === "<w:t>") {
inChunk = true;
}
if (inChunk) {
if (part.type === "placeholder" && !part.module) {
chunk[0].value = '<w:t xml:space="preserve">';
}
chunk.push(part);
} else {
parsed.push(part);
}
if (part.type === "tag" && part.position === "end" && part.text && part.value === "</w:t>") {
Array.prototype.push.apply(parsed, chunk);
inChunk = false;
chunk = [];
}
return parsed;
}, []);
Array.prototype.push.apply(result, chunk);
return result;
}
};
module.exports = function () {
return wrapper(spacePreserve);
};
},{"../module-wrapper":9}],15:[function(require,module,exports){
"use strict";
var DocUtils = require("./doc-utils");
var parser = {
postparse: function postparse(parsed, modules) {
function getTraits(traitName, parsed) {
return modules.map(function (module) {
return module.getTraits(traitName, parsed);
});
}
function postparse(parsed) {
return modules.reduce(function (parsed, module) {
return module.postparse(parsed, { postparse: postparse, getTraits: getTraits });
}, parsed);
}
return postparse(parsed);
},
parse: function parse(lexed, modules) {
function moduleParse(placeHolderContent, parsed) {
var moduleParsed = void 0;
for (var i = 0, l = modules.length; i < l; i++) {
var _module = modules[i];
moduleParsed = _module.parse(placeHolderContent);
if (moduleParsed) {
parsed.push(moduleParsed);
return moduleParsed;
}
}
return null;
}
var inPlaceHolder = false;
var placeHolderContent = void 0;
var tailParts = [];
return lexed.reduce(function (parsed, token) {
if (token.type === "delimiter") {
inPlaceHolder = token.position === "start";
if (token.position === "end") {
placeHolderContent = DocUtils.wordToUtf8(placeHolderContent);
if (!moduleParse(placeHolderContent, parsed)) {
parsed.push({ type: "placeholder", value: placeHolderContent });
}
Array.prototype.push.apply(parsed, tailParts);
tailParts = [];
return parsed;
}
placeHolderContent = "";
return parsed;
}
if (inPlaceHolder) {
if (token.type === "content" && token.position === "insidetag") {
placeHolderContent += token.value;
} else {
tailParts.push(token);
}
return parsed;
}
parsed.push(token);
return parsed;
}, []);
}
};
module.exports = parser;
},{"./doc-utils":2}],16:[function(require,module,exports){
"use strict";
var ScopeManager = require("./scope-manager");
var DocUtils = require("./doc-utils");
function moduleRender(part, options) {
var moduleRendered = void 0;
for (var i = 0, l = options.modules.length; i < l; i++) {
var _module = options.modules[i];
moduleRendered = _module.render(part, options);
if (moduleRendered) {
return moduleRendered;
}
}
return false;
}
function render(options) {
options.render = render;
options.modules = options.modules;
if (!options.scopeManager) {
options.scopeManager = ScopeManager.createBaseScopeManager(options);
}
return options.compiled.map(function (part) {
var moduleRendered = moduleRender(part, options);
if (moduleRendered) {
return moduleRendered.value;
}
if (part.type === "placeholder") {
var value = options.scopeManager.getValue(part.value);
if (value == null) {
value = options.nullGetter(part);
}
return DocUtils.utf8ToWord(value);
}
if (part.type === "content" || part.type === "tag") {
return part.value;
}
throw new Error("Unimplemented tag type \"" + part.type + "\"");
}).join("");
}
module.exports = render;
},{"./doc-utils":2,"./scope-manager":17}],17:[function(require,module,exports){
"use strict";
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var Errors = require("./errors");
// This class responsibility is to manage the scope
var ScopeManager = function () {
function ScopeManager(options) {
_classCallCheck(this, ScopeManager);
this.scopePath = options.scopePath;
this.scopeList = options.scopeList;
this.parser = options.parser;
}
_createClass(ScopeManager, [{
key: "loopOver",
value: function loopOver(tag, callback, inverted) {
inverted = inverted || false;
return this.loopOverValue(this.getValue(tag), callback, inverted);
}
}, {
key: "functorIfInverted",
value: function functorIfInverted(inverted, functor, value) {
if (inverted) {
functor(value);
}
}
}, {
key: "isValueFalsy",
value: function isValueFalsy(value, type) {
return value == null || !value || type === "[object Array]" && value.length === 0;
}
}, {
key: "loopOverValue",
value: function loopOverValue(value, functor, inverted) {
var type = Object.prototype.toString.call(value);
var currentValue = this.scopeList[this.num];
if (this.isValueFalsy(value, type)) {
return this.functorIfInverted(inverted, functor, currentValue);
}
if (type === "[object Array]") {
for (var i = 0, scope; i < value.length; i++) {
scope = value[i];
this.functorIfInverted(!inverted, functor, scope);
}
return;
}
if (type === "[object Object]") {
return this.functorIfInverted(!inverted, functor, value);
}
if (value === true) {
return this.functorIfInverted(!inverted, functor, currentValue);
}
}
}, {
key: "getValue",
value: function getValue(tag, num) {
// search in the scopes (in reverse order) and keep the first defined value
this.num = num == null ? this.scopeList.length - 1 : num;
var err = void 0;
var parser = void 0;
var result = void 0;
var scope = this.scopeList[this.num];
try {
parser = this.parser(tag);
} catch (error) {
err = new Errors.XTScopeParserError("Scope parser compilation failed");
err.properties = {
id: "scopeparser_compilation_failed",
tag: tag,
explanation: "The scope parser for the tag " + tag + " failed to compile",
rootError: error
};
throw err;
}
try {
result = parser.get(scope, { num: this.num, scopeList: this.scopeList });
} catch (error) {
err = new Errors.XTScopeParserError("Scope parser execution failed");
err.properties = {
id: "scopeparser_execution_failed",
explanation: "The scope parser for the tag " + tag + " failed to execute",
scope: scope,
tag: tag,
rootError: error
};
throw err;
}
if (result == null && this.num > 0) {
return this.getValue(tag, this.num - 1);
}
return result;
}
}, {
key: "createSubScopeManager",
value: function createSubScopeManager(scope, tag) {
var options = {
scopePath: this.scopePath.slice(0),
scopeList: this.scopeList.slice(0)
};
options.parser = this.parser;
options.scopeList = this.scopeList.concat(scope);
options.scopePath = this.scopePath.concat(tag);
return new ScopeManager(options);
}
}]);
return ScopeManager;
}();
ScopeManager.createBaseScopeManager = function (_ref) {
var parser = _ref.parser,
tags = _ref.tags;
var options = { parser: parser, tags: tags };
options.scopePath = [];
options.scopeList = [tags];
return new ScopeManager(options);
};
module.exports = ScopeManager;
},{"./errors":4}],18:[function(require,module,exports){
"use strict";
var DocUtils = require("./doc-utils");
var Errors = require("./errors");
function throwRawTagNotInParagraph(options) {
var err = new Errors.XTTemplateError("Raw tag not in paragraph");
var tag = options.part.value;
err.properties = {
id: "raw_tag_outerxml_invalid",
explanation: "The tag \"" + tag + "\"",
rootError: options.rootError,
xtag: tag,
postparsed: options.postparsed,
expandTo: options.expandTo,
index: options.index
};
throw err;
}
function lastTagIsOpenTag(array, tag) {
if (array.length === 0) {
return false;
}
var lastTag = array[array.length - 1];
var innerLastTag = lastTag.tag.substr(1);
var innerCurrentTag = tag.substr(2, tag.length - 3);
return innerLastTag.indexOf(innerCurrentTag) === 0;
}
function addTag(array, tag) {
array.push({ tag: tag });
return array;
}
function getListXmlElements(parts) {
/*
get the different closing and opening tags between two texts (doesn't take into account tags that are opened then closed (those that are closed then opened are returned)):
returns:[{"tag":"</w:r>","offset":13},{"tag":"</w:p>","offset":265},{"tag":"</w:tc>","offset":271},{"tag":"<w:tc>","offset":828},{"tag":"<w:p>","offset":883},{"tag":"<w:r>","offset":1483}]
*/
var tags = parts.filter(function (part) {
return part.type === "tag";
}).map(function (part) {
return part.value;
});
var result = [];
for (var i = 0, tag; i < tags.length; i++) {
tag = tags[i];
// closing tag
if (tag[1] === "/") {
if (lastTagIsOpenTag(result, tag)) {
result.pop();
} else {
result = addTag(result, tag);
}
} else if (tag[tag.length - 1] !== "/") {
result = addTag(result, tag);
}
}
return result;
}
function getExpandToDefault(parts) {
var xmlElements = getListXmlElements(parts);
for (var i = 0; i < xmlElements.length; i++) {
var xmlElement = xmlElements[i];
if (xmlElement.tag.indexOf("<w:tc") === 0) {
return "w:tr";
}
if (xmlElement.tag.indexOf("<a:tc") === 0) {
return "a:tr";
}
}
return false;
}
function expandOne(part, postparsed, options) {
var expandTo = part.expandTo || options.expandTo;
var index = postparsed.indexOf(part);
if (!expandTo) {
return postparsed;
}
var right = void 0,
left = void 0;
try {
right = DocUtils.getRight(postparsed, expandTo, index);
left = DocUtils.getLeft(postparsed, expandTo, index);
} catch (rootError) {
if (rootError instanceof Errors.XTTemplateError) {
throwRawTagNotInParagraph({ part: part, rootError: rootError, postparsed: postparsed, expandTo: expandTo, index: index });
}
throw rootError;
}
var leftParts = postparsed.slice(left, index);
var rightParts = postparsed.slice(index + 1, right + 1);
var inner = options.getInner({ index: index, part: part, leftParts: leftParts, rightParts: rightParts, left: left, right: right, postparsed: postparsed });
if (!inner.length) {
inner.expanded = [leftParts, rightParts];
inner = [inner];
}
return DocUtils.concatArrays([postparsed.slice(0, left), inner, postparsed.slice(right + 1)]);
}
function expandToOne(postparsed, options) {
var expandToElements = postparsed.reduce(function (elements, part) {
if (part.type === "placeholder" && part.module === options.moduleName) {
elements.push(part);
}
return elements;
}, []);
expandToElements.forEach(function (part) {
postparsed = expandOne(part, postparsed, options);
});
return postparsed;
}
module.exports = {
expandToOne: expandToOne,
getExpandToDefault: getExpandToDefault
};
},{"./doc-utils":2,"./errors":4}],19:[function(require,module,exports){
"use strict";
// res class responsibility is to parse the XML.
var DocUtils = require("./doc-utils");
var memoize = require("./memoize");
function handleRecursiveCase(res) {
/*
Because xmlTemplater is recursive (meaning it can call it self), we need to handle special cases where the XML is not valid:
For example with res string "I am</w:t></w:r></w:p><w:p><w:r><w:t>sleeping",
- we need to match also the string that is inside an implicit <w:t> (that's the role of replacerUnshift) (in res case 'I am')
- we need to match the string that is at the right of a <w:t> (that's the role of replacerPush) (in res case 'sleeping')
the test: describe "scope calculation" it "should compute the scope between 2 <w:t>" makes sure that res part of code works
It should even work if they is no XML at all, for example if the code is just "I am sleeping", in res case however, they should only be one match
*/
function replacerUnshift() {
var pn = { array: Array.prototype.slice.call(arguments) };
pn.array.shift();
var match = pn.array[0] + pn.array[1];
// add match so that pn[0] = whole match, pn[1]= first parenthesis,...
pn.array.unshift(match);
pn.array.pop();
var offset = pn.array.pop();
pn.offset = offset;
pn.first = true;
// add at the beginning
res.matches.unshift(pn);
res.charactersAdded.unshift(0);
return res.charactersAddedCumulative.unshift(0);
}
if (res.content.indexOf("<") === -1 && res.content.indexOf(">") === -1) {
res.content.replace(/^()([^<>]*)$/, replacerUnshift);
}
var r = new RegExp("^()([^<]+)</(?:" + res.tagsXmlArrayJoined + ")>");
res.content.replace(r, replacerUnshift);
function replacerPush() {
var pn = { array: Array.prototype.slice.call(arguments) };
pn.array.pop();
var offset = pn.array.pop();
pn.offset = offset;
pn.last = true;
// add at the end
res.matches.push(pn);
res.charactersAdded.push(0);
return res.charactersAddedCumulative.push(0);
}
r = new RegExp("(<(?:" + res.tagsXmlArrayJoined + ")[^>]*>)([^>]+)$");
res.content.replace(r, replacerPush);
return res;
}
function xmlMatcher(content, tagsXmlArray) {
var res = {};
res.content = content;
res.tagsXmlArray = tagsXmlArray;
res.tagsXmlArrayJoined = res.tagsXmlArray.join("|");
var regexp = new RegExp("(<(?:" + res.tagsXmlArrayJoined + ")[^>]*>)([^<>]*)</(?:" + res.tagsXmlArrayJoined + ")>", "g");
res.matc