UNPKG

docxtemplater

Version:

docx and pptx generator working with templates and data (like Mustache, for Word and Powerpoint documents)

570 lines (467 loc) 17.7 kB
"use strict"; function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); } function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); } function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } 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; } 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; } 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, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } var _require = require("../doc-utils.js"), mergeObjects = _require.mergeObjects, chunkBy = _require.chunkBy, last = _require.last, isParagraphStart = _require.isParagraphStart, isParagraphEnd = _require.isParagraphEnd, isContent = _require.isContent, startsWith = _require.startsWith, isTagEnd = _require.isTagEnd, isTagStart = _require.isTagStart, getSingleAttribute = _require.getSingleAttribute, setSingleAttribute = _require.setSingleAttribute; var wrapper = require("../module-wrapper.js"); var moduleName = "loop"; function hasContent(parts) { return parts.some(function (part) { return isContent(part); }); } function getFirstMeaningFulPart(parsed) { for (var i = 0, len = parsed.length; i < len; i++) { if (parsed[i].type !== "content") { return parsed[i]; } } return null; } function isInsideParagraphLoop(part) { var firstMeaningfulPart = getFirstMeaningFulPart(part.subparsed); return firstMeaningfulPart != null && firstMeaningfulPart.tag !== "w:t"; } function getPageBreakIfApplies(part) { return part.hasPageBreak && isInsideParagraphLoop(part) ? '<w:p><w:r><w:br w:type="page"/></w:r></w:p>' : ""; } function isEnclosedByParagraphs(parsed) { return parsed.length && isParagraphStart(parsed[0]) && isParagraphEnd(last(parsed)); } function getOffset(chunk) { return hasContent(chunk) ? 0 : chunk.length; } function addPageBreakAtEnd(subRendered) { var found = false; var i = subRendered.parts.length - 1; for (var j = subRendered.parts.length - 1; i >= 0; i--) { var p = subRendered.parts[j]; if (p === "</w:p>" && !found) { found = true; subRendered.parts.splice(j, 0, '<w:r><w:br w:type="page"/></w:r>'); break; } } if (!found) { subRendered.parts.push('<w:p><w:r><w:br w:type="page"/></w:r></w:p>'); } } function addPageBreakAtBeginning(subRendered) { subRendered.parts.unshift('<w:p><w:r><w:br w:type="page"/></w:r></w:p>'); } function isContinuous(parts) { return parts.some(function (part) { return part.type === "tag" && part.tag === "w:type" && part.value.indexOf("continuous") !== -1; }); } function addContinuousType(parts) { var stop = false; var inSectPr = false; return parts.reduce(function (result, part) { if (stop === false && startsWith(part, "<w:sectPr")) { inSectPr = true; } if (inSectPr) { if (startsWith(part, "<w:type")) { stop = true; } if (stop === false && startsWith(part, "</w:sectPr")) { result.push('<w:type w:val="continuous"/>'); } } result.push(part); return result; }, []); } function dropHeaderFooterRefs(parts) { return parts.filter(function (text) { return !startsWith(text, "<w:headerReference") && !startsWith(text, "<w:footerReference"); }); } function hasPageBreak(chunk) { return chunk.some(function (part) { return part.tag === "w:br" && part.value.indexOf('w:type="page"') !== -1; }); } function hasImage(chunk) { return chunk.some(function (_ref) { var tag = _ref.tag; return tag === "w:drawing"; }); } function getSectPr(chunks) { var collectSectPr = false; var sectPrs = []; chunks.forEach(function (part) { if (isTagStart("w:sectPr", part)) { sectPrs.push([]); collectSectPr = true; } if (collectSectPr) { sectPrs[sectPrs.length - 1].push(part); } if (isTagEnd("w:sectPr", part)) { collectSectPr = false; } }); return sectPrs; } function getSectPrHeaderFooterChangeCount(chunks) { var collectSectPr = false; var sectPrCount = 0; chunks.forEach(function (part) { if (isTagStart("w:sectPr", part)) { collectSectPr = true; } if (collectSectPr) { if (part.tag === "w:headerReference" || part.tag === "w:footerReference") { sectPrCount++; collectSectPr = false; } } if (isTagEnd("w:sectPr", part)) { collectSectPr = false; } }); return sectPrCount; } function getLastSectPr(parsed) { var sectPr = []; var inSectPr = false; for (var i = parsed.length - 1; i >= 0; i--) { var part = parsed[i]; if (isTagEnd("w:sectPr", part)) { inSectPr = true; } if (isTagStart("w:sectPr", part)) { sectPr.unshift(part); inSectPr = false; } if (inSectPr) { sectPr.unshift(part); } if (isParagraphStart(part)) { if (sectPr.length > 0) { return sectPr.map(function (_ref2) { var value = _ref2.value; return value; }).join(""); } break; } } return ""; } var LoopModule = /*#__PURE__*/function () { function LoopModule() { _classCallCheck(this, LoopModule); this.name = "LoopModule"; this.inXfrm = false; this.totalSectPr = 0; this.prefix = { start: "#", end: "/", dash: /^-([^\s]+)\s(.+)$/, inverted: "^" }; } _createClass(LoopModule, [{ key: "parse", value: function parse(placeHolderContent, _ref3) { var match = _ref3.match, getValue = _ref3.getValue, getValues = _ref3.getValues; var module = moduleName; var type = "placeholder"; var _this$prefix = this.prefix, start = _this$prefix.start, inverted = _this$prefix.inverted, dash = _this$prefix.dash, end = _this$prefix.end; if (match(start, placeHolderContent)) { return { type: type, value: getValue(start, placeHolderContent), expandTo: "auto", module: module, location: "start", inverted: false }; } if (match(inverted, placeHolderContent)) { return { type: type, value: getValue(inverted, placeHolderContent), expandTo: "auto", module: module, location: "start", inverted: true }; } if (match(end, placeHolderContent)) { return { type: type, value: getValue(end, placeHolderContent), module: module, location: "end" }; } if (match(dash, placeHolderContent)) { var _getValues = getValues(dash, placeHolderContent), _getValues2 = _slicedToArray(_getValues, 3), expandTo = _getValues2[1], value = _getValues2[2]; return { type: type, value: value, expandTo: expandTo, module: module, location: "start", inverted: false }; } return null; } }, { key: "getTraits", value: function getTraits(traitName, parsed) { if (traitName !== "expandPair") { return; } return parsed.reduce(function (tags, part, offset) { if (part.type === "placeholder" && part.module === moduleName && part.subparsed == null) { tags.push({ part: part, offset: offset }); } return tags; }, []); } }, { key: "preparse", value: function preparse(parsed) { this.sects = getSectPr(parsed); } }, { key: "postparse", value: function postparse(parsed, _ref4) { var basePart = _ref4.basePart; if (basePart) { basePart.sectPrCount = getSectPrHeaderFooterChangeCount(parsed); this.totalSectPr += basePart.sectPrCount; var sects = this.sects; sects.some(function (sect, index) { if (sect[0].lIndex > basePart.lIndex) { if (index + 1 < sects.length && isContinuous(sects[index + 1])) { basePart.addContinuousType = true; } return true; } }); basePart.lastParagrapSectPr = getLastSectPr(parsed); } if (!basePart || basePart.expandTo !== "auto" || basePart.module !== moduleName || !isEnclosedByParagraphs(parsed)) { return parsed; } basePart.paragraphLoop = true; var level = 0; var chunks = chunkBy(parsed, function (p) { if (isParagraphStart(p)) { level++; if (level === 1) { return "start"; } } if (isParagraphEnd(p)) { level--; if (level === 0) { return "end"; } } return null; }); var firstChunk = chunks[0]; var lastChunk = last(chunks); var firstOffset = getOffset(firstChunk); var lastOffset = getOffset(lastChunk); basePart.hasPageBreakBeginning = hasPageBreak(firstChunk); basePart.hasPageBreak = hasPageBreak(lastChunk); if (firstOffset === 0 || lastOffset === 0) { return parsed; } if (hasImage(firstChunk)) { firstOffset = 0; } if (hasImage(lastChunk)) { lastOffset = 0; } return parsed.slice(firstOffset, parsed.length - lastOffset); } // eslint-disable-next-line complexity }, { key: "render", value: function render(part, options) { if (part.tag === "p:xfrm") { this.inXfrm = part.position === "start"; } if (part.tag === "a:ext" && this.inXfrm) { this.lastExt = part; return part; } if (part.type !== "placeholder" || part.module !== moduleName) { return null; } var totalValue = []; var errors = []; var heightOffset = 0; var firstTag = part.subparsed[0]; var tagHeight = 0; if (firstTag.tag === "a:tr") { tagHeight = +getSingleAttribute(firstTag.value, "h"); } heightOffset -= tagHeight; var a16RowIdOffset = 0; function loopOver(scope, i, length) { heightOffset += tagHeight; var scopeManager = options.scopeManager.createSubScopeManager(scope, part.value, i, part, length); part.subparsed.forEach(function (pp) { if (pp.type === "tag" && pp.tag === "a16:rowId") { var val = +getSingleAttribute(pp.value, "val") + a16RowIdOffset; a16RowIdOffset = 1; pp.value = setSingleAttribute(pp.value, "val", val); } }); var subRendered = options.render(mergeObjects({}, options, { compiled: part.subparsed, tags: {}, scopeManager: scopeManager })); if (part.hasPageBreak && i === length - 1 && isInsideParagraphLoop(part)) { addPageBreakAtEnd(subRendered); } var isNotFirst = scopeManager.scopePathItem.some(function (i) { return i !== 0; }); if (isNotFirst) { if (part.sectPrCount === 1) { subRendered.parts = dropHeaderFooterRefs(subRendered.parts); } if (part.addContinuousType) { subRendered.parts = addContinuousType(subRendered.parts); } } if (part.hasPageBreakBeginning && isInsideParagraphLoop(part)) { addPageBreakAtBeginning(subRendered); } totalValue = totalValue.concat(subRendered.parts); errors = errors.concat(subRendered.errors || []); } var result; try { result = options.scopeManager.loopOver(part.value, loopOver, part.inverted, { part: part }); } catch (e) { errors.push(e); return { errors: errors }; } // if the loop is showing empty content if (result === false) { if (part.lastParagrapSectPr) { if (part.paragraphLoop) { return { value: "<w:p><w:pPr>".concat(part.lastParagrapSectPr, "</w:pPr></w:p>") }; } return { value: "</w:t></w:r></w:p><w:p><w:pPr>".concat(part.lastParagrapSectPr, "</w:pPr><w:r><w:t>") }; } return { value: getPageBreakIfApplies(part) || "", errors: errors }; } if (heightOffset !== 0) { var cy = +getSingleAttribute(this.lastExt.value, "cy"); this.lastExt.value = setSingleAttribute(this.lastExt.value, "cy", cy + heightOffset); } return { value: options.joinUncorrupt(totalValue, _objectSpread(_objectSpread({}, options), {}, { basePart: part })), errors: errors }; } }, { key: "resolve", value: function resolve(part, options) { if (part.type !== "placeholder" || part.module !== moduleName) { return null; } var sm = options.scopeManager; var promisedValue = sm.getValueAsync(part.value, { part: part }); var promises = []; function loopOver(scope, i, length) { var scopeManager = sm.createSubScopeManager(scope, part.value, i, part, length); promises.push(options.resolve({ filePath: options.filePath, modules: options.modules, baseNullGetter: options.baseNullGetter, resolve: options.resolve, compiled: part.subparsed, tags: {}, scopeManager: scopeManager })); } var errorList = []; return promisedValue.then(function (value) { sm.loopOverValue(value, loopOver, part.inverted); return Promise.all(promises).then(function (r) { return r.map(function (_ref5) { var resolved = _ref5.resolved, errors = _ref5.errors; errorList.push.apply(errorList, _toConsumableArray(errors)); return resolved; }); }).then(function (value) { if (errorList.length > 0) { throw errorList; } return value; }); }); } }]); return LoopModule; }(); module.exports = function () { return wrapper(new LoopModule()); };