525 lines
21 KiB
JavaScript
525 lines
21 KiB
JavaScript
"use strict";
|
|
|
|
var _excluded = ["modules"];
|
|
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); }
|
|
function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
|
|
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
|
|
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a 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, _toPropertyKey(descriptor.key), descriptor); } }
|
|
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
|
|
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); }
|
|
var DocUtils = require("./doc-utils.js");
|
|
DocUtils.traits = require("./traits.js");
|
|
DocUtils.moduleWrapper = require("./module-wrapper.js");
|
|
var createScope = require("./scope-manager.js");
|
|
var _require = require("./errors.js"),
|
|
throwMultiError = _require.throwMultiError,
|
|
throwResolveBeforeCompile = _require.throwResolveBeforeCompile,
|
|
throwRenderInvalidTemplate = _require.throwRenderInvalidTemplate,
|
|
throwRenderTwice = _require.throwRenderTwice;
|
|
var logErrors = require("./error-logger.js");
|
|
var collectContentTypes = require("./collect-content-types.js");
|
|
var ctXML = "[Content_Types].xml";
|
|
var relsFile = "_rels/.rels";
|
|
var commonModule = require("./modules/common.js");
|
|
var Lexer = require("./lexer.js");
|
|
var defaults = DocUtils.defaults,
|
|
str2xml = DocUtils.str2xml,
|
|
xml2str = DocUtils.xml2str,
|
|
moduleWrapper = DocUtils.moduleWrapper,
|
|
concatArrays = DocUtils.concatArrays,
|
|
uniq = DocUtils.uniq,
|
|
getDuplicates = DocUtils.getDuplicates,
|
|
stableSort = DocUtils.stableSort;
|
|
var _require2 = require("./errors.js"),
|
|
XTInternalError = _require2.XTInternalError,
|
|
throwFileTypeNotIdentified = _require2.throwFileTypeNotIdentified,
|
|
throwFileTypeNotHandled = _require2.throwFileTypeNotHandled,
|
|
throwApiVersionError = _require2.throwApiVersionError;
|
|
var currentModuleApiVersion = [3, 38, 0];
|
|
function dropUnsupportedFileTypesModules(dx) {
|
|
dx.modules = dx.modules.filter(function (module) {
|
|
if (module.supportedFileTypes) {
|
|
if (!Array.isArray(module.supportedFileTypes)) {
|
|
throw new Error("The supportedFileTypes field of the module must be an array");
|
|
}
|
|
var isSupportedModule = module.supportedFileTypes.indexOf(dx.fileType) !== -1;
|
|
if (!isSupportedModule) {
|
|
module.on("detached");
|
|
}
|
|
return isSupportedModule;
|
|
}
|
|
return true;
|
|
});
|
|
}
|
|
var Docxtemplater = /*#__PURE__*/function () {
|
|
function Docxtemplater(zip) {
|
|
var _this = this;
|
|
var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
|
|
_ref$modules = _ref.modules,
|
|
modules = _ref$modules === void 0 ? [] : _ref$modules,
|
|
options = _objectWithoutProperties(_ref, _excluded);
|
|
_classCallCheck(this, Docxtemplater);
|
|
if (!Array.isArray(modules)) {
|
|
throw new Error("The modules argument of docxtemplater's constructor must be an array");
|
|
}
|
|
this.targets = [];
|
|
this.rendered = false;
|
|
this.scopeManagers = {};
|
|
this.compiled = {};
|
|
this.modules = [commonModule()];
|
|
this.setOptions(options);
|
|
modules.forEach(function (module) {
|
|
_this.attachModule(module);
|
|
});
|
|
if (arguments.length > 0) {
|
|
if (!zip || !zip.files || typeof zip.file !== "function") {
|
|
throw new Error("The first argument of docxtemplater's constructor must be a valid zip file (jszip v2 or pizzip v3)");
|
|
}
|
|
this.loadZip(zip);
|
|
this.compile();
|
|
this.v4Constructor = true;
|
|
}
|
|
}
|
|
return _createClass(Docxtemplater, [{
|
|
key: "verifyApiVersion",
|
|
value: function verifyApiVersion(neededVersion) {
|
|
neededVersion = neededVersion.split(".").map(function (i) {
|
|
return parseInt(i, 10);
|
|
});
|
|
if (neededVersion.length !== 3) {
|
|
throwApiVersionError("neededVersion is not a valid version", {
|
|
neededVersion: neededVersion,
|
|
explanation: "the neededVersion must be an array of length 3"
|
|
});
|
|
}
|
|
if (neededVersion[0] !== currentModuleApiVersion[0]) {
|
|
throwApiVersionError("The major api version do not match, you probably have to update docxtemplater with npm install --save docxtemplater", {
|
|
neededVersion: neededVersion,
|
|
currentModuleApiVersion: currentModuleApiVersion,
|
|
explanation: "moduleAPIVersionMismatch : needed=".concat(neededVersion.join("."), ", current=").concat(currentModuleApiVersion.join("."))
|
|
});
|
|
}
|
|
if (neededVersion[1] > currentModuleApiVersion[1]) {
|
|
throwApiVersionError("The minor api version is not uptodate, you probably have to update docxtemplater with npm install --save docxtemplater", {
|
|
neededVersion: neededVersion,
|
|
currentModuleApiVersion: currentModuleApiVersion,
|
|
explanation: "moduleAPIVersionMismatch : needed=".concat(neededVersion.join("."), ", current=").concat(currentModuleApiVersion.join("."))
|
|
});
|
|
}
|
|
if (neededVersion[1] === currentModuleApiVersion[1] && neededVersion[2] > currentModuleApiVersion[2]) {
|
|
throwApiVersionError("The patch api version is not uptodate, you probably have to update docxtemplater with npm install --save docxtemplater", {
|
|
neededVersion: neededVersion,
|
|
currentModuleApiVersion: currentModuleApiVersion,
|
|
explanation: "moduleAPIVersionMismatch : needed=".concat(neededVersion.join("."), ", current=").concat(currentModuleApiVersion.join("."))
|
|
});
|
|
}
|
|
return true;
|
|
}
|
|
}, {
|
|
key: "setModules",
|
|
value: function setModules(obj) {
|
|
this.modules.forEach(function (module) {
|
|
module.set(obj);
|
|
});
|
|
}
|
|
}, {
|
|
key: "sendEvent",
|
|
value: function sendEvent(eventName) {
|
|
this.modules.forEach(function (module) {
|
|
module.on(eventName);
|
|
});
|
|
}
|
|
}, {
|
|
key: "attachModule",
|
|
value: function attachModule(module) {
|
|
if (this.v4Constructor) {
|
|
throw new XTInternalError("attachModule() should not be called manually when using the v4 constructor");
|
|
}
|
|
var moduleType = _typeof(module);
|
|
if (moduleType === "function") {
|
|
throw new XTInternalError("Cannot attach a class/function as a module. Most probably you forgot to instantiate the module by using `new` on the module.");
|
|
}
|
|
if (!module || moduleType !== "object") {
|
|
throw new XTInternalError("Cannot attachModule with a falsy value");
|
|
}
|
|
if (module.requiredAPIVersion) {
|
|
this.verifyApiVersion(module.requiredAPIVersion);
|
|
}
|
|
if (module.attached === true) {
|
|
if (typeof module.clone === "function") {
|
|
module = module.clone();
|
|
} else {
|
|
throw new Error("Cannot attach a module that was already attached : \"".concat(module.name, "\". The most likely cause is that you are instantiating the module at the root level, and using it for multiple instances of Docxtemplater"));
|
|
}
|
|
}
|
|
module.attached = true;
|
|
var wrappedModule = moduleWrapper(module);
|
|
this.modules.push(wrappedModule);
|
|
wrappedModule.on("attached");
|
|
if (this.fileType) {
|
|
dropUnsupportedFileTypesModules(this);
|
|
}
|
|
return this;
|
|
}
|
|
}, {
|
|
key: "setOptions",
|
|
value: function setOptions(options) {
|
|
var _this2 = this;
|
|
if (this.v4Constructor) {
|
|
throw new Error("setOptions() should not be called manually when using the v4 constructor");
|
|
}
|
|
if (!options) {
|
|
throw new Error("setOptions should be called with an object as first parameter");
|
|
}
|
|
this.options = {};
|
|
Object.keys(defaults).forEach(function (key) {
|
|
var defaultValue = defaults[key];
|
|
_this2.options[key] = options[key] != null ? options[key] : _this2[key] || defaultValue;
|
|
_this2[key] = _this2.options[key];
|
|
});
|
|
this.delimiters.start = DocUtils.utf8ToWord(this.delimiters.start);
|
|
this.delimiters.end = DocUtils.utf8ToWord(this.delimiters.end);
|
|
return this;
|
|
}
|
|
}, {
|
|
key: "loadZip",
|
|
value: function loadZip(zip) {
|
|
if (this.v4Constructor) {
|
|
throw new Error("loadZip() should not be called manually when using the v4 constructor");
|
|
}
|
|
if (zip.loadAsync) {
|
|
throw new XTInternalError("Docxtemplater doesn't handle JSZip version >=3, please use pizzip");
|
|
}
|
|
this.zip = zip;
|
|
this.updateFileTypeConfig();
|
|
this.modules = concatArrays([this.fileTypeConfig.baseModules.map(function (moduleFunction) {
|
|
return moduleFunction();
|
|
}), this.modules]);
|
|
dropUnsupportedFileTypesModules(this);
|
|
return this;
|
|
}
|
|
}, {
|
|
key: "precompileFile",
|
|
value: function precompileFile(fileName) {
|
|
var currentFile = this.createTemplateClass(fileName);
|
|
currentFile.preparse();
|
|
this.compiled[fileName] = currentFile;
|
|
}
|
|
}, {
|
|
key: "compileFile",
|
|
value: function compileFile(fileName) {
|
|
this.compiled[fileName].parse();
|
|
}
|
|
}, {
|
|
key: "getScopeManager",
|
|
value: function getScopeManager(to, currentFile, tags) {
|
|
if (!this.scopeManagers[to]) {
|
|
this.scopeManagers[to] = createScope({
|
|
tags: tags,
|
|
parser: this.parser,
|
|
cachedParsers: currentFile.cachedParsers
|
|
});
|
|
}
|
|
return this.scopeManagers[to];
|
|
}
|
|
}, {
|
|
key: "resolveData",
|
|
value: function resolveData(data) {
|
|
var _this3 = this;
|
|
var errors = [];
|
|
if (!Object.keys(this.compiled).length) {
|
|
throwResolveBeforeCompile();
|
|
}
|
|
return Promise.resolve(data).then(function (data) {
|
|
_this3.setData(data);
|
|
_this3.setModules({
|
|
data: _this3.data,
|
|
Lexer: Lexer
|
|
});
|
|
_this3.mapper = _this3.modules.reduce(function (value, module) {
|
|
return module.getRenderedMap(value);
|
|
}, {});
|
|
return Promise.all(Object.keys(_this3.mapper).map(function (to) {
|
|
var _this3$mapper$to = _this3.mapper[to],
|
|
from = _this3$mapper$to.from,
|
|
data = _this3$mapper$to.data;
|
|
return Promise.resolve(data).then(function (data) {
|
|
var currentFile = _this3.compiled[from];
|
|
currentFile.filePath = to;
|
|
currentFile.scopeManager = _this3.getScopeManager(to, currentFile, data);
|
|
return currentFile.resolveTags(data).then(function (result) {
|
|
currentFile.scopeManager.finishedResolving = true;
|
|
return result;
|
|
}, function (errs) {
|
|
Array.prototype.push.apply(errors, errs);
|
|
});
|
|
});
|
|
})).then(function (resolved) {
|
|
if (errors.length !== 0) {
|
|
if (_this3.options.errorLogging) {
|
|
logErrors(errors, _this3.options.errorLogging);
|
|
}
|
|
throwMultiError(errors);
|
|
}
|
|
return concatArrays(resolved);
|
|
});
|
|
});
|
|
}
|
|
}, {
|
|
key: "reorderModules",
|
|
value: function reorderModules() {
|
|
this.modules = stableSort(this.modules, function (m1, m2) {
|
|
return (m2.priority || 0) - (m1.priority || 0);
|
|
});
|
|
}
|
|
}, {
|
|
key: "throwIfDuplicateModules",
|
|
value: function throwIfDuplicateModules() {
|
|
var duplicates = getDuplicates(this.modules.map(function (_ref2) {
|
|
var name = _ref2.name;
|
|
return name;
|
|
}));
|
|
if (duplicates.length > 0) {
|
|
throw new XTInternalError("Detected duplicate module \"".concat(duplicates[0], "\""));
|
|
}
|
|
}
|
|
}, {
|
|
key: "compile",
|
|
value: function compile() {
|
|
var _this4 = this;
|
|
this.updateFileTypeConfig();
|
|
this.throwIfDuplicateModules();
|
|
this.reorderModules();
|
|
if (Object.keys(this.compiled).length) {
|
|
return this;
|
|
}
|
|
this.options = this.modules.reduce(function (options, module) {
|
|
return module.optionsTransformer(options, _this4);
|
|
}, this.options);
|
|
this.options.xmlFileNames = uniq(this.options.xmlFileNames);
|
|
this.xmlDocuments = this.options.xmlFileNames.reduce(function (xmlDocuments, fileName) {
|
|
var content = _this4.zip.files[fileName].asText();
|
|
xmlDocuments[fileName] = str2xml(content);
|
|
return xmlDocuments;
|
|
}, {});
|
|
this.setModules({
|
|
zip: this.zip,
|
|
xmlDocuments: this.xmlDocuments
|
|
});
|
|
this.getTemplatedFiles();
|
|
// Loop inside all templatedFiles (ie xml files with content).
|
|
// Sometimes they don't exist (footer.xml for example)
|
|
this.templatedFiles.forEach(function (fileName) {
|
|
if (_this4.zip.files[fileName] != null) {
|
|
_this4.precompileFile(fileName);
|
|
}
|
|
});
|
|
this.templatedFiles.forEach(function (fileName) {
|
|
if (_this4.zip.files[fileName] != null) {
|
|
_this4.compileFile(fileName);
|
|
}
|
|
});
|
|
this.setModules({
|
|
compiled: this.compiled
|
|
});
|
|
verifyErrors(this);
|
|
return this;
|
|
}
|
|
}, {
|
|
key: "getRelsTypes",
|
|
value: function getRelsTypes() {
|
|
var rootRels = this.zip.files[relsFile];
|
|
var rootRelsXml = rootRels ? str2xml(rootRels.asText()) : null;
|
|
var rootRelationships = rootRelsXml ? rootRelsXml.getElementsByTagName("Relationship") : [];
|
|
var relsTypes = {};
|
|
for (var i = 0, len = rootRelationships.length; i < len; i++) {
|
|
var r = rootRelationships[i];
|
|
relsTypes[r.getAttribute("Target")] = r.getAttribute("Type");
|
|
}
|
|
return relsTypes;
|
|
}
|
|
}, {
|
|
key: "getContentTypes",
|
|
value: function getContentTypes() {
|
|
var contentTypes = this.zip.files[ctXML];
|
|
var contentTypeXml = contentTypes ? str2xml(contentTypes.asText()) : null;
|
|
var overrides = contentTypeXml ? contentTypeXml.getElementsByTagName("Override") : null;
|
|
var defaults = contentTypeXml ? contentTypeXml.getElementsByTagName("Default") : null;
|
|
return {
|
|
overrides: overrides,
|
|
defaults: defaults,
|
|
contentTypes: contentTypes,
|
|
contentTypeXml: contentTypeXml
|
|
};
|
|
}
|
|
}, {
|
|
key: "updateFileTypeConfig",
|
|
value: function updateFileTypeConfig() {
|
|
var _this5 = this;
|
|
var fileType;
|
|
if (this.zip.files.mimetype) {
|
|
fileType = "odt";
|
|
}
|
|
this.relsTypes = this.getRelsTypes();
|
|
var _this$getContentTypes = this.getContentTypes(),
|
|
overrides = _this$getContentTypes.overrides,
|
|
defaults = _this$getContentTypes.defaults,
|
|
contentTypes = _this$getContentTypes.contentTypes,
|
|
contentTypeXml = _this$getContentTypes.contentTypeXml;
|
|
if (contentTypeXml) {
|
|
this.filesContentTypes = collectContentTypes(overrides, defaults, this.zip);
|
|
this.invertedContentTypes = DocUtils.invertMap(this.filesContentTypes);
|
|
this.setModules({
|
|
contentTypes: this.contentTypes,
|
|
invertedContentTypes: this.invertedContentTypes
|
|
});
|
|
}
|
|
this.modules.forEach(function (module) {
|
|
fileType = module.getFileType({
|
|
zip: _this5.zip,
|
|
contentTypes: contentTypes,
|
|
contentTypeXml: contentTypeXml,
|
|
overrides: overrides,
|
|
defaults: defaults,
|
|
doc: _this5
|
|
}) || fileType;
|
|
});
|
|
if (fileType === "odt") {
|
|
throwFileTypeNotHandled(fileType);
|
|
}
|
|
if (!fileType) {
|
|
throwFileTypeNotIdentified();
|
|
}
|
|
this.fileType = fileType;
|
|
dropUnsupportedFileTypesModules(this);
|
|
this.fileTypeConfig = this.options.fileTypeConfig || this.fileTypeConfig || Docxtemplater.FileTypeConfig[this.fileType]();
|
|
return this;
|
|
}
|
|
}, {
|
|
key: "renderAsync",
|
|
value: function renderAsync(data) {
|
|
var _this6 = this;
|
|
return this.resolveData(data).then(function () {
|
|
return _this6.render();
|
|
});
|
|
}
|
|
}, {
|
|
key: "render",
|
|
value: function render(data) {
|
|
var _this7 = this;
|
|
if (this.rendered) {
|
|
throwRenderTwice();
|
|
}
|
|
this.rendered = true;
|
|
this.compile();
|
|
if (this.errors.length > 0) {
|
|
throwRenderInvalidTemplate();
|
|
}
|
|
if (data) {
|
|
this.setData(data);
|
|
}
|
|
this.setModules({
|
|
data: this.data,
|
|
Lexer: Lexer
|
|
});
|
|
this.mapper = this.mapper || this.modules.reduce(function (value, module) {
|
|
return module.getRenderedMap(value);
|
|
}, {});
|
|
Object.keys(this.mapper).forEach(function (to) {
|
|
var _this7$mapper$to = _this7.mapper[to],
|
|
from = _this7$mapper$to.from,
|
|
data = _this7$mapper$to.data;
|
|
var currentFile = _this7.compiled[from];
|
|
currentFile.scopeManager = _this7.getScopeManager(to, currentFile, data);
|
|
currentFile.render(to);
|
|
_this7.zip.file(to, currentFile.content, {
|
|
createFolders: true
|
|
});
|
|
});
|
|
verifyErrors(this);
|
|
this.sendEvent("syncing-zip");
|
|
this.syncZip();
|
|
return this;
|
|
}
|
|
}, {
|
|
key: "syncZip",
|
|
value: function syncZip() {
|
|
var _this8 = this;
|
|
Object.keys(this.xmlDocuments).forEach(function (fileName) {
|
|
_this8.zip.remove(fileName);
|
|
var content = xml2str(_this8.xmlDocuments[fileName]);
|
|
return _this8.zip.file(fileName, content, {
|
|
createFolders: true
|
|
});
|
|
});
|
|
}
|
|
}, {
|
|
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 content = this.zip.files[path].asText();
|
|
return this.createTemplateClassFromContent(content, path);
|
|
}
|
|
}, {
|
|
key: "createTemplateClassFromContent",
|
|
value: function createTemplateClassFromContent(content, filePath) {
|
|
var _this9 = this;
|
|
var xmltOptions = {
|
|
filePath: filePath,
|
|
contentType: this.filesContentTypes[filePath],
|
|
relsType: this.relsTypes[filePath]
|
|
};
|
|
Object.keys(defaults).concat(["filesContentTypes", "fileTypeConfig", "fileType", "modules"]).forEach(function (key) {
|
|
xmltOptions[key] = _this9[key];
|
|
});
|
|
return new Docxtemplater.XmlTemplater(content, xmltOptions);
|
|
}
|
|
}, {
|
|
key: "getFullText",
|
|
value: function getFullText(path) {
|
|
return this.createTemplateClass(path || this.fileTypeConfig.textPath(this)).getFullText();
|
|
}
|
|
}, {
|
|
key: "getTemplatedFiles",
|
|
value: function getTemplatedFiles() {
|
|
var _this10 = this;
|
|
this.templatedFiles = this.fileTypeConfig.getTemplatedFiles(this.zip);
|
|
this.targets.forEach(function (target) {
|
|
_this10.templatedFiles.push(target);
|
|
});
|
|
this.templatedFiles = uniq(this.templatedFiles);
|
|
return this.templatedFiles;
|
|
}
|
|
}]);
|
|
}();
|
|
function verifyErrors(doc) {
|
|
var compiled = doc.compiled;
|
|
doc.errors = concatArrays(Object.keys(compiled).map(function (name) {
|
|
return compiled[name].allErrors;
|
|
}));
|
|
if (doc.errors.length !== 0) {
|
|
if (doc.options.errorLogging) {
|
|
logErrors(doc.errors, doc.options.errorLogging);
|
|
}
|
|
throwMultiError(doc.errors);
|
|
}
|
|
}
|
|
Docxtemplater.DocUtils = DocUtils;
|
|
Docxtemplater.Errors = require("./errors.js");
|
|
Docxtemplater.XmlTemplater = require("./xml-templater.js");
|
|
Docxtemplater.FileTypeConfig = require("./file-type-config.js");
|
|
Docxtemplater.XmlMatcher = require("./xml-matcher.js");
|
|
module.exports = Docxtemplater;
|
|
module.exports["default"] = Docxtemplater; |