docxtemplater
Version:
docx and pptx generator working with templates and data (like Mustache, for Word and Powerpoint documents)
560 lines (444 loc) • 13.4 kB
JavaScript
;
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
var _require = require("xmldom"),
DOMParser = _require.DOMParser,
XMLSerializer = _require.XMLSerializer;
var _require2 = require("./errors.js"),
throwXmlTagNotFound = _require2.throwXmlTagNotFound;
var _require3 = require("./utils.js"),
last = _require3.last,
first = _require3.first;
function parser(tag) {
return {
get: function get(scope) {
if (tag === ".") {
return scope;
}
return scope[tag];
}
};
}
function getNearestLeftIndex(parsed, elements, index) {
for (var i = index; i >= 0; i--) {
var part = parsed[i];
for (var j = 0, len = elements.length; j < len; j++) {
var element = elements[j];
if (isStarting(part.value, element)) {
return j;
}
}
}
return null;
}
function getNearestRightIndex(parsed, elements, index) {
for (var i = index, l = parsed.length; i < l; i++) {
var part = parsed[i];
for (var j = 0, len = elements.length; j < len; j++) {
var element = elements[j];
if (isEnding(part.value, element)) {
return j;
}
}
}
return -1;
}
function getNearestLeft(parsed, elements, index) {
var found = getNearestLeftIndex(parsed, elements, index);
if (found !== -1) {
return elements[found];
}
return null;
}
function getNearestRight(parsed, elements, index) {
var found = getNearestRightIndex(parsed, elements, index);
if (found !== -1) {
return elements[found];
}
return null;
}
function buildNearestCache(postparsed, tags) {
return postparsed.reduce(function (cached, part, i) {
if (part.type === "tag" && tags.indexOf(part.tag) !== -1) {
cached.push({
i: i,
part: part
});
}
return cached;
}, []);
}
function getNearestLeftIndexWithCache(index, cache) {
if (cache.length === 0) {
return -1;
}
for (var i = 0, len = cache.length; i < len; i++) {
var current = cache[i];
var next = cache[i + 1];
if (current.i < index && (!next || index < next.i) && current.part.position === "start") {
return i;
}
}
return -1;
}
function getNearestLeftWithCache(index, cache) {
var found = getNearestLeftIndexWithCache(index, cache);
if (found !== -1) {
return cache[found].part.tag;
}
return null;
}
function getNearestRightIndexWithCache(index, cache) {
if (cache.length === 0) {
return -1;
}
for (var i = 0, len = cache.length; i < len; i++) {
var current = cache[i];
var _last = cache[i - 1];
if (index < current.i && (!_last || _last.i < index) && current.part.position === "end") {
return i;
}
}
return -1;
}
function getNearestRightWithCache(index, cache) {
var found = getNearestRightIndexWithCache(index, cache);
if (found !== -1) {
return cache[found].part.tag;
}
return null;
}
function endsWith(str, suffix) {
return str.indexOf(suffix, str.length - suffix.length) !== -1;
}
function startsWith(str, prefix) {
return str.substring(0, prefix.length) === prefix;
}
function uniq(arr) {
var hash = {},
result = [];
for (var i = 0, l = arr.length; i < l; ++i) {
if (!hash.hasOwnProperty(arr[i])) {
hash[arr[i]] = true;
result.push(arr[i]);
}
}
return result;
}
function chunkBy(parsed, f) {
return parsed.reduce(function (chunks, p) {
var currentChunk = last(chunks);
var res = f(p);
if (currentChunk.length === 0) {
currentChunk.push(p);
return chunks;
}
if (res === "start") {
chunks.push([p]);
} else if (res === "end") {
currentChunk.push(p);
chunks.push([]);
} else {
currentChunk.push(p);
}
return chunks;
}, [[]]).filter(function (p) {
return p.length > 0;
});
}
var defaults = {
paragraphLoop: false,
nullGetter: function nullGetter(part) {
if (!part.module) {
return "undefined";
}
if (part.module === "rawxml") {
return "";
}
return "";
},
xmlFileNames: [],
parser: parser,
linebreaks: false,
fileTypeConfig: null,
delimiters: {
start: "{",
end: "}"
}
};
function mergeObjects() {
var resObj = {};
var obj, keys;
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;
}
function xml2str(xmlNode) {
var a = new XMLSerializer();
return a.serializeToString(xmlNode).replace(/xmlns(:[a-z0-9]+)?="" ?/g, "");
}
function str2xml(str) {
if (str.charCodeAt(0) === 65279) {
// BOM sequence
str = str.substr(1);
}
var parser = new DOMParser();
return parser.parseFromString(str, "text/xml");
}
var charMap = [["&", "&"], ["<", "<"], [">", ">"], ['"', """], ["'", "'"]];
function escapeRegExp(str) {
// to be able to use a string as a regex
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
var charMapRegexes = charMap.map(function (_ref) {
var _ref2 = _slicedToArray(_ref, 2),
endChar = _ref2[0],
startChar = _ref2[1];
return {
rstart: new RegExp(escapeRegExp(startChar), "g"),
rend: new RegExp(escapeRegExp(endChar), "g"),
start: startChar,
end: endChar
};
});
function wordToUtf8(string) {
var r;
for (var i = charMapRegexes.length - 1; i >= 0; i--) {
r = charMapRegexes[i];
string = string.replace(r.rstart, r.end);
}
return string;
}
function utf8ToWord(string) {
if (typeof string !== "string") {
string = string.toString();
}
var r;
for (var i = 0, l = charMapRegexes.length; i < l; i++) {
r = charMapRegexes[i];
string = string.replace(r.rend, r.start);
}
return string;
} // This function is written with for loops for performance
function concatArrays(arrays) {
var result = [];
for (var i = 0; i < arrays.length; i++) {
var array = arrays[i];
for (var j = 0, len = array.length; j < len; j++) {
result.push(array[j]);
}
}
return result;
}
var spaceRegexp = new RegExp(String.fromCharCode(160), "g");
function convertSpaces(s) {
return s.replace(spaceRegexp, " ");
}
function pregMatchAll(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;
while ((match = regex.exec(content)) != null) {
matchArray.push({
array: match,
offset: match.index
});
}
return matchArray;
}
function isEnding(value, element) {
return value === "</" + element + ">";
}
function isStarting(value, element) {
return value.indexOf("<" + element) === 0 && [">", " "].indexOf(value[element.length + 1]) !== -1;
}
function getRight(parsed, element, index) {
var val = getRightOrNull(parsed, element, index);
if (val !== null) {
return val;
}
throwXmlTagNotFound({
position: "right",
element: element,
parsed: parsed,
index: index
});
}
function getRightOrNull(parsed, elements, index) {
if (typeof elements === "string") {
elements = [elements];
}
var level = 1;
for (var i = index, l = parsed.length; i < l; i++) {
var part = parsed[i];
for (var j = 0, len = elements.length; j < len; j++) {
var element = elements[j];
if (isEnding(part.value, element)) {
level--;
}
if (isStarting(part.value, element)) {
level++;
}
if (level === 0) {
return i;
}
}
}
return null;
}
function getLeft(parsed, element, index) {
var val = getLeftOrNull(parsed, element, index);
if (val !== null) {
return val;
}
throwXmlTagNotFound({
position: "left",
element: element,
parsed: parsed,
index: index
});
}
function getLeftOrNull(parsed, elements, index) {
if (typeof elements === "string") {
elements = [elements];
}
var level = 1;
for (var i = index; i >= 0; i--) {
var part = parsed[i];
for (var j = 0, len = elements.length; j < len; j++) {
var element = elements[j];
if (isStarting(part.value, element)) {
level--;
}
if (isEnding(part.value, element)) {
level++;
}
if (level === 0) {
return i;
}
}
}
return null;
}
function isTagStart(tagType, _ref3) {
var type = _ref3.type,
tag = _ref3.tag,
position = _ref3.position;
return type === "tag" && tag === tagType && position === "start";
}
function isTagEnd(tagType, _ref4) {
var type = _ref4.type,
tag = _ref4.tag,
position = _ref4.position;
return type === "tag" && tag === tagType && position === "end";
}
function isParagraphStart(options) {
return isTagStart("w:p", options) || isTagStart("a:p", options);
}
function isParagraphEnd(options) {
return isTagEnd("w:p", options) || isTagEnd("a:p", options);
}
function isTextStart(part) {
return part.type === "tag" && part.position === "start" && part.text;
}
function isTextEnd(part) {
return part.type === "tag" && part.position === "end" && part.text;
}
function isContent(p) {
return p.type === "placeholder" || p.type === "content" && p.position === "insidetag";
}
var corruptCharacters = /[\x00-\x08\x0B\x0C\x0E-\x1F]/; // 00 NUL '\0' (null character)
// 01 SOH (start of heading)
// 02 STX (start of text)
// 03 ETX (end of text)
// 04 EOT (end of transmission)
// 05 ENQ (enquiry)
// 06 ACK (acknowledge)
// 07 BEL '\a' (bell)
// 08 BS '\b' (backspace)
// 0B VT '\v' (vertical tab)
// 0C FF '\f' (form feed)
// 0E SO (shift out)
// 0F SI (shift in)
// 10 DLE (data link escape)
// 11 DC1 (device control 1)
// 12 DC2 (device control 2)
// 13 DC3 (device control 3)
// 14 DC4 (device control 4)
// 15 NAK (negative ack.)
// 16 SYN (synchronous idle)
// 17 ETB (end of trans. blk)
// 18 CAN (cancel)
// 19 EM (end of medium)
// 1A SUB (substitute)
// 1B ESC (escape)
// 1C FS (file separator)
// 1D GS (group separator)
// 1E RS (record separator)
// 1F US (unit separator)
function hasCorruptCharacters(string) {
return corruptCharacters.test(string);
}
function invertMap(map) {
return Object.keys(map).reduce(function (invertedMap, key) {
var value = map[key];
invertedMap[value] = invertedMap[value] || [];
invertedMap[value].push(key);
return invertedMap;
}, {});
}
module.exports = {
endsWith: endsWith,
startsWith: startsWith,
getNearestLeft: getNearestLeft,
getNearestRight: getNearestRight,
getNearestLeftWithCache: getNearestLeftWithCache,
getNearestRightWithCache: getNearestRightWithCache,
getNearestLeftIndex: getNearestLeftIndex,
getNearestRightIndex: getNearestRightIndex,
getNearestLeftIndexWithCache: getNearestLeftIndexWithCache,
getNearestRightIndexWithCache: getNearestRightIndexWithCache,
buildNearestCache: buildNearestCache,
isContent: isContent,
isParagraphStart: isParagraphStart,
isParagraphEnd: isParagraphEnd,
isTagStart: isTagStart,
isTagEnd: isTagEnd,
isTextStart: isTextStart,
isTextEnd: isTextEnd,
uniq: uniq,
chunkBy: chunkBy,
last: last,
first: first,
mergeObjects: mergeObjects,
xml2str: xml2str,
str2xml: str2xml,
getRightOrNull: getRightOrNull,
getRight: getRight,
getLeftOrNull: getLeftOrNull,
getLeft: getLeft,
pregMatchAll: pregMatchAll,
convertSpaces: convertSpaces,
escapeRegExp: escapeRegExp,
charMapRegexes: charMapRegexes,
hasCorruptCharacters: hasCorruptCharacters,
defaults: defaults,
wordToUtf8: wordToUtf8,
utf8ToWord: utf8ToWord,
concatArrays: concatArrays,
invertMap: invertMap,
charMap: charMap
};