@ind-rcg/plugins-printengine 250.1004.0 → 252.1008.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -424,7 +424,7 @@ eval("/*\n * FILE_HEADER\n */\n\n\nconst _ = __webpack_require__(/*! lodash */ \
424
424
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
425
425
 
426
426
  "use strict";
427
- eval("/*\n * FILE_HEADER\n */\n\n\nconst classPrintEngineParams = __webpack_require__(/*! ../src/printEngineParams */ \"./src/printEngineParams.js\");\nconst classLocalization = __webpack_require__(/*! ./localizationClass */ \"./src/localizationClass.js\");\nconst classToggles = __webpack_require__(/*! ./togglesClass */ \"./src/togglesClass.js\");\nconst classMacroHandler = __webpack_require__(/*! ./macroHandlerClass */ \"./src/macroHandlerClass.js\");\nconst PdfConverter = __webpack_require__(/*! ./pdfConverterClass */ \"./src/pdfConverterClass.js\");\nconst ContractToIntermediateJSON = __webpack_require__(/*! ./contractToIntermediateJSONClass */ \"./src/contractToIntermediateJSONClass.js\");\nconst classLog = __webpack_require__(/*! ./logClass */ \"./src/logClass.js\");\nlet __log = new classLog();\nconst contractParser= new ContractToIntermediateJSON(__log );\n\nconst stream = __webpack_require__(/*! stream */ \"./node_modules/stream-browserify/index.js\");\nconst _ = __webpack_require__(/*! lodash */ \"./node_modules/lodash/lodash.js\");\n\nlet pdfConverter = new PdfConverter();\n\n// This will always stay undefined, and will only be activated via Rewire for tests\nlet testReportName;\n\nconst PRINT_TYPE = {\n \"STREAM\": \"STREAM\",\n \"DATA_URL\": \"DATA_URL\",\n \"BLOB\": \"BLOB\"\n};\nObject.freeze(PRINT_TYPE);\n\nfunction __validateCommonParameters(contract, params, format){\n if (typeof contract !== 'string') {\n throw new TypeError(\"Not a valid contract object\");\n }\n\n if (!(params instanceof classPrintEngineParams)){\n throw new TypeError(\"Not a valid PrintEngineParams object\");\n }\n\n if ((typeof params.getBOs() !== 'object') || (_.isEmpty(params.getBOs()))) {\n throw new TypeError(\"Not a valid business object dictionary\");\n }\n\n let localization = params.getLocalization();\n\n if ((typeof localization !== 'object') || (Object.keys(localization).length === 0)) {\n throw new TypeError(\"Not a valid localization object\");\n }\n\n if(!PdfConverter.isValidFormat(format)) {\n throw new TypeError(\"Not a valid print format\");\n }\n}\n\nfunction __innerPrintLogic(printType, contract, params, _stream, format) {\n let json = contractParser.toJson(contract, params);\n let pdfDefinition = pdfConverter.toPdfDefinition(json, format, testReportName);\n\n switch (printType) {\n case PRINT_TYPE.STREAM:\n pdfConverter.writeToStream(pdfDefinition, _stream);\n break;\n\n case PRINT_TYPE.BLOB:\n return pdfConverter.toBlob(pdfDefinition);\n \n case PRINT_TYPE.DATA_URL:\n return pdfConverter.toDataUrl(pdfDefinition); \n\n default:\n __log.error('PRINT_TYPE ' + printType + ' not supported in innerPrintLogic');\n break;\n }\n}\n\nfunction printToStream(contract, params, _stream, format = \"A4\") {\n // Validate parameters\n if(!(_stream instanceof stream.Stream)) {\n throw new TypeError(\"Not a valid stream.\");\n }\n __validateCommonParameters(contract, params, format);\n __innerPrintLogic(PRINT_TYPE.STREAM, contract, params, _stream, format);\n}\n\nfunction printToDataUrl(contract, params, format = \"A4\") {\n // Validate parameters\n __validateCommonParameters(contract, params, format);\n return __innerPrintLogic(PRINT_TYPE.DATA_URL, contract, params, null, format);\n}\n\nfunction printToBlob(contract, params, format = \"A4\") {\n // Validate parameters\n __validateCommonParameters(contract, params, format);\n return __innerPrintLogic(PRINT_TYPE.BLOB, contract, params, null, format);\n}\n\n\nmodule.exports = {\n \"printToStream\": printToStream,\n \"printToDataUrl\": printToDataUrl,\n \"printToBlob\": printToBlob,\n \"PdfConverter\": PdfConverter,\n \"ContractToIntermediateJSON\": ContractToIntermediateJSON,\n \"Localization\": classLocalization,\n \"Toggles\": classToggles,\n \"PrintEngineParams\": classPrintEngineParams,\n \"MacroHandler\": classMacroHandler,\n \"Log\": classLog,\n \"onMessage\": __log.onMessage\n};\n\n\n//# sourceURL=webpack://__FWPrinting/./src/index.js?");
427
+ eval("/*\n * FILE_HEADER\n */\n\n\nconst classPrintEngineParams = __webpack_require__(/*! ../src/printEngineParams */ \"./src/printEngineParams.js\");\nconst classLocalization = __webpack_require__(/*! ./localizationClass */ \"./src/localizationClass.js\");\nconst classToggles = __webpack_require__(/*! ./togglesClass */ \"./src/togglesClass.js\");\nconst classMacroHandler = __webpack_require__(/*! ./macroHandlerClass */ \"./src/macroHandlerClass.js\");\nconst PdfConverter = __webpack_require__(/*! ./pdfConverterClass */ \"./src/pdfConverterClass.js\");\nconst ContractToIntermediateJSON = __webpack_require__(/*! ./contractToIntermediateJSONClass */ \"./src/contractToIntermediateJSONClass.js\");\nconst classLog = __webpack_require__(/*! ./logClass */ \"./src/logClass.js\");\nlet __log = new classLog();\nconst contractParser= new ContractToIntermediateJSON(__log );\n\nconst stream = __webpack_require__(/*! stream */ \"./node_modules/stream-browserify/index.js\");\nconst _ = __webpack_require__(/*! lodash */ \"./node_modules/lodash/lodash.js\");\n\nlet pdfConverter = new PdfConverter();\n\n// This will always stay undefined, and will only be activated via Rewire for tests\nlet testReportName;\n\nconst PRINT_TYPE = {\n \"STREAM\": \"STREAM\",\n \"DATA_URL\": \"DATA_URL\",\n \"BLOB\": \"BLOB\"\n};\nObject.freeze(PRINT_TYPE);\n\nfunction __validateCommonParameters(contract, params, format){\n if (typeof contract !== 'string') {\n throw new TypeError(\"Not a valid contract object\");\n }\n\n if (!(params instanceof classPrintEngineParams)){\n throw new TypeError(\"Not a valid PrintEngineParams object\");\n }\n\n if ((typeof params.getBOs() !== 'object') || (_.isEmpty(params.getBOs()))) {\n throw new TypeError(\"Not a valid business object dictionary\");\n }\n\n let localization = params.getLocalization();\n\n if ((typeof localization !== 'object') || (Object.keys(localization).length === 0)) {\n throw new TypeError(\"Not a valid localization object\");\n }\n\n if(!PdfConverter.isValidFormat(format)) {\n throw new TypeError(\"Not a valid print format\");\n }\n}\n\nfunction __innerPrintLogic(printType, contract, params, _stream, format, config) {\n let json = contractParser.toJson(contract, params);\n let pdfDefinition = pdfConverter.toPdfDefinition(json, format, testReportName);\n switch (printType) {\n case PRINT_TYPE.STREAM:\n pdfConverter.writeToStream(pdfDefinition, _stream);\n break;\n\n case PRINT_TYPE.BLOB:\n return new Promise((resolve, reject) => {\n pdfConverter.toBlob(pdfDefinition).then((blobData)=>{\n if(config && config.metaData === true){\n resolve({\n data: blobData,\n pdfJson: json\n });\n } else {\n resolve(blobData);\n }\n }, (err)=>{\n reject(err);\n });\n });\n case PRINT_TYPE.DATA_URL:\n return pdfConverter.toDataUrl(pdfDefinition); \n\n default:\n __log.error('PRINT_TYPE ' + printType + ' not supported in innerPrintLogic');\n break;\n }\n}\n\nfunction printToStream(contract, params, _stream, format = \"A4\", config = {}) {\n // Validate parameters\n if(!(_stream instanceof stream.Stream)) {\n throw new TypeError(\"Not a valid stream.\");\n }\n __validateCommonParameters(contract, params, format);\n __innerPrintLogic(PRINT_TYPE.STREAM, contract, params, _stream, format, config);\n}\n\nfunction printToDataUrl(contract, params, format = \"A4\", config = {}) {\n // Validate parameters\n __validateCommonParameters(contract, params, format);\n return __innerPrintLogic(PRINT_TYPE.DATA_URL, contract, params, null, format, config);\n}\n\nfunction printToBlob(contract, params, format = \"A4\", config = {}) {\n // Validate parameters\n __validateCommonParameters(contract, params, format);\n return __innerPrintLogic(PRINT_TYPE.BLOB, contract, params, null, format, config);\n}\n\n\nmodule.exports = {\n \"printToStream\": printToStream,\n \"printToDataUrl\": printToDataUrl,\n \"printToBlob\": printToBlob,\n \"PdfConverter\": PdfConverter,\n \"ContractToIntermediateJSON\": ContractToIntermediateJSON,\n \"Localization\": classLocalization,\n \"Toggles\": classToggles,\n \"PrintEngineParams\": classPrintEngineParams,\n \"MacroHandler\": classMacroHandler,\n \"Log\": classLog,\n \"onMessage\": __log.onMessage\n};\n\n\n//# sourceURL=webpack://__FWPrinting/./src/index.js?");
428
428
 
429
429
  /***/ }),
430
430
 
@@ -468,7 +468,7 @@ eval("/*\n * FILE_HEADER\n */\n\n\nconst LogClass = __webpack_require__(/*! ./lo
468
468
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
469
469
 
470
470
  "use strict";
471
- eval("/*\n * FILE_HEADER\n */\n\n\nconst _ = __webpack_require__(/*! lodash */ \"./node_modules/lodash/lodash.js\");\nconst PdfPrinter = __webpack_require__(/*! pdfmake */ \"./node_modules/pdfmake/build/pdfmake.js\");\nconst Format = __webpack_require__(/*! ./formatClass */ \"./src/formatClass.js\");\nconst TableCellIdentifier = __webpack_require__(/*! ./tableCellIdentifier */ \"./src/tableCellIdentifier.js\");\n\n// required for webpack include (browser impl), used in conjunction with BrowserFonts definition\nconst BrowserFontsVfs = __webpack_require__(/*! pdfmake/build/vfs_fonts.js */ \"./node_modules/pdfmake/build/vfs_fonts.js\");\n\n// => use 'Roboto' font (pdfMake default) due to licensing (Apache 2.0)\n// https://fonts.google.com/specimen/Roboto || https://en.wikipedia.org/wiki/Roboto\nconst ServerFonts = {\n Roboto: {\n normal: './fonts/Roboto-Regular.ttf',\n bold: './fonts/Roboto-Medium.ttf',\n italics: './fonts/Roboto-Italic.ttf',\n bolditalics: './fonts/Roboto-MediumItalic.ttf'\n }\n};\n\nconst BrowserFonts = {\n Roboto: {\n normal: 'Roboto-Regular.ttf',\n bold: 'Roboto-Medium.ttf',\n italics: 'Roboto-Italic.ttf',\n bolditalics: 'Roboto-MediumItalic.ttf'\n },\n PrintFont: {\n normal: 'Regular',\n bold: 'Bold',\n italics: 'Italic',\n bolditalics: 'BoldItalic'\n }\n};\n\nconst TableLayouts = {\n lightHorizontalLinesMainItemsOnly: {\n hLineWidth: function (i, node) {\n // no frame for the table\n if (i === 0 || i === node.table.body.length) {\n return 0;\n }\n // bold seperator between header and body\n if (i === node.table.headerRows) {\n return 2;\n }\n // get first cell id for row ...\n let row = node.table.body[i];\n if (!_.isNil(row)) {\n let cellId = null;\n _.forEach(row, cell =>{\n if(_.has(cell, 'id')) {\n cellId = cell.id;\n return false;\n }\n });\n // seperator for between main rows (+ their child rows)\n let tcid = TableCellIdentifier.fromString(cellId);\n if (!_.isNil(tcid)) {\n if (tcid.isKnown() && tcid.belongsToMainRow()) {\n // seperator between main rows\n return 1;\n } else if (!tcid.isKnown()) {\n // seperator for 'unknown row'\n return 1;\n }\n }\n }\n // no seperator for all other cases, e.g. child rows\n return 0;\n },\n vLineWidth: function () {\n return 0;\n },\n hLineColor: function (i, node) {\n return i === node.table.headerRows ? 'black' : 'gray';\n }\n }\n};\n\nconst STYLE_HEADING1 = \"heading1\";\nconst STYLE_HEADING2 = \"heading2\";\nconst STYLE_PARAGRAPH = \"paragraph\";\n\nconst EXPORT_TYPE = {\n \"BASE_64\" : \"BASE_64\",\n \"DATA_URL\" : \"DATA_URL\",\n \"BLOB\" : \"BLOB\"\n};\nObject.freeze(EXPORT_TYPE);\n\nclass PdfConverter {\n constructor() {\n this.__pdfMake = null;\n if(typeof pdfMake !== \"undefined\")\n {\n this.__pdfMake = pdfMake;\n }\n\n this.__format = new Format();\n }\n\n __applyPageBreakData(pdfDefinition) {\n if (!_.isUndefined(pdfDefinition.dynamicPageBreak) && pdfDefinition.dynamicPageBreak && \n !_.isUndefined(pdfDefinition.dynamicPageBreakData) && _.isArray(pdfDefinition.dynamicPageBreakData) && pdfDefinition.dynamicPageBreakData.length > 0) {\n // let table = pdfDefinition.content[0].table;\n let dynamicPageBreakData = pdfDefinition.dynamicPageBreakData;\n \n // handle tables in body\n let tables = _.filter(pdfDefinition.content, {style: 'tableBody'});\n this.__applyPageBreakDataToTables(tables, dynamicPageBreakData);\n }\n } \n\n __applyPageBreakDataToTables(tables, dynamicPageBreakData) {\n\n if (!_.isNil(tables) && _.isArray(tables) && tables.length > 0 && !_.isNil(dynamicPageBreakData)) {\n for (let i = 0; i < tables.length; i++) {\n // get table\n let table = tables[i].table;\n if (!_.isNil(table) && !_.isUndefined(table.dynamicPageBreak) && table.dynamicPageBreak) {\n // loop rows\n let row = null;\n let cell = null;\n let breakRow = false;\n for (let j = 0; j < table.body.length; j++) { \n row = table.body[j];\n breakRow = false;\n // loop columns\n for (let k = 0; k < row.length; k++) {\n cell = row[k];\n // apply manual pageBreaks instead of dynamic ones\n if (!breakRow && _.has(cell, 'id')) {\n breakRow = _.includes(dynamicPageBreakData, cell.id);\n if (breakRow) {\n cell.pageBreak = 'before';\n } \n } else if (breakRow && _.has(cell, 'id')) {\n cell.pageBreak = 'before';\n }\n }\n }\n }\n }\n }\n\n }\n \n __initializePdfDefinition() {\n this.__definition = {\n \"content\": [],\n pageSize: 'A4',\n pageMargins: [ 40, 60, 40, 60 ],\n defaultStyle: {\n font: 'Roboto', //'Helvetica'\n },\n styles: {\n tableBody: {\n fontSize: 10,\n margin: [0, 5, 0, 15]\n },\n tableHeader: {\n fontSize: 10,\n bold: true\n },\n heading1: {\n fontSize: 18,\n bold: true,\n margin: [0, 0, 0, 10]\n },\n heading2: {\n fontSize: 14,\n bold: true,\n margin: [0, 10, 0, 5]\n },\n paragraph: {\n fontSize: 10,\n bold: false,\n italics: false\n }\n }\n };\n this.__automaticPageBreak = false;\n }\n\n __getThOrTdContent(thTdNode, settings) {\n let result = {};\n let text = \"\";\n\n if(!_.isNil(thTdNode.elements)){\n _.forEach(thTdNode.elements, childElement => {\n if(childElement.type === \"text\") {\n text = text + childElement.text;\n } else if (childElement.type === \"element\" && childElement.name === \"pageNumber\" && !_.isNil(settings.currentPage)) {\n text = text + settings.currentPage;\n } else if (childElement.type === \"element\" && childElement.name === \"img\") {\n result.image = this.__getImageDefinition(childElement, false);\n }\n });\n }\n result.text = text;\n\n return result;\n }\n\n __getHeadingDefinition(headingNode, headingStyle) {\n return this.__createHeadingOrParagraphText(headingNode, headingNode.elements[0].text, headingStyle);\n }\n\n __getParagraphDefinition(paragraphNode, paragraphStyle) {\n return this.__createHeadingOrParagraphText(paragraphNode, paragraphNode.elements[0].text, paragraphStyle);\n }\n\n __getImageDefinition(imageNode, useAlignment) {\n let img = {};\n\n if (!_.isNil(imageNode)){\n let atr = imageNode.attributes;\n let imageId = atr.id;\n let mimeType = atr.mimeType;\n\n if (!_.isNil(imageId) && this.__isImageCached(imageId)) {\n // => png / jpeg image already in cache => simply (re)use it ...\n img = {image: imageId};\n\n } else {\n\n if (mimeType === \"image/svg+xml\") {\n // => svg image handling (vector graphics)\n let src = atr.src.split(\",\");\n let data = src[1];\n let txt;\n\n if ((typeof window === 'object') && (typeof window.atob === 'function')) {\n // we do expect an utf8 string\n txt = decodeURIComponent(encodeURIComponent(window.atob(data)));\n } else {\n let buf = Buffer.from(data, 'base64');\n txt = buf.toString('utf8');\n }\n img = {svg: txt};\n\n } else {\n // => png / jpeg image handling (raster graphics)\n // add image to cache\n this.__addImageToCache(imageId, atr.src);\n img = {image: imageId}; \n\n }\n } \n\n if (!_.isNil(atr.width)) {\n img.width = parseInt(atr.width, 10);\n }\n if (!_.isNil(atr.height)) {\n img.height = parseInt(atr.height, 10);\n }\n if (!_.isNil(atr.fit)) {\n let fit = atr.fit.split(',');\n let w = parseInt(fit[0], 10);\n let h = parseInt(fit[1], 10);\n img.fit = [w,h];\n }\n\n if (!_.isNil(atr.alignment) && (true === useAlignment)) {\n let alignmentAttribute = this.__checkEnumAttribute(imageNode, 'alignment', [\"left\", \"center\", \"right\"], null);\n\n if (!_.isNil(alignmentAttribute)) {\n img.alignment = alignmentAttribute;\n }\n }\n }\n\n return img;\n }\n\n __addImageToCache(imageId, imageData) {\n // init image cache if required\n if (!_.has(this.__definition, 'images')) { \n _.assign(this.__definition, {\n images: {}\n });\n }\n\n // add image to cache\n if (!_.has(this.__definition.images, imageId)) {\n this.__definition.images[imageId] = imageData;\n }\n }\n\n __isImageCached(imageId) {\n return (_.has(this.__definition, 'images') && _.has(this.__definition.images, imageId));\n }\n\n __checkSpansAndColumns(pdfTableDefinition) {\n let rows = 0;\n let columns = 0;\n\n let rowCount = pdfTableDefinition.table.body.length;\n let columnCount = pdfTableDefinition.table.widths.length;\n\n for (rows=0; rows<rowCount; rows++) {\n let row = pdfTableDefinition.table.body[rows];\n\n if (row.length > columnCount) {\n row.length = columnCount;\n } else if (row.length < columnCount) {\n do {\n row.push(\"\");\n } while(row.length < columnCount);\n }\n\n let maxRowSpan = rowCount-rows;\n\n for (columns=0; columns<columnCount; columns++) {\n let column = row[columns];\n let maxColSpan = columnCount-columns;\n\n if (!_.isString(column)) {\n if (!_.isNil(column[\"colSpan\"])) {\n if (column.colSpan > maxColSpan) {\n column.colSpan = maxColSpan;\n }\n if (column.colSpan < 2) {\n delete column.colSpan;\n }\n if ((Object.keys(column).length === 1) && !_.isNil(column[\"text\"])) {\n row[columns] = column.text;\n }\n }\n if (!_.isNil(column[\"rowSpan\"])) {\n if (column.rowSpan > maxRowSpan) {\n column.rowSpan = maxRowSpan;\n }\n if (column.rowSpan < 2) {\n delete column.rowSpan;\n }\n if ((Object.keys(column).length === 1) && !_.isNil(column[\"text\"])) {\n row[columns] = column.text;\n }\n }\n }\n }\n }\n }\n\n __checkIntegerAttribute(element, attributeName, allowedStrings, onlyPositiveNumbers, defaultValue) {\n let bElement = !_.isNil(element) && _.isObject(element.attributes);\n let bAttribute = bElement && _.isString(attributeName) && (attributeName !== \"\") && !_.isNil(element.attributes[attributeName]);\n let bAllowedStrings = !_.isNil(allowedStrings) && _.isArray(allowedStrings) && (allowedStrings.length > 0);\n let bPositiveNumbers = !_.isNil(onlyPositiveNumbers) && _.isBoolean(onlyPositiveNumbers) && (onlyPositiveNumbers === true);\n\n if (bAttribute) {\n let attribute = element.attributes[attributeName];\n let i = 0;\n\n if (bAllowedStrings && _.isString(attribute)){\n for (i=0; i<allowedStrings.length; i++) {\n if (attribute === allowedStrings[i]) {\n return attribute;\n }\n }\n }\n\n let parsed = parseInt(attribute, 10);\n\n if(!isNaN(parsed)) {\n if (bPositiveNumbers && (parsed < 0))\n {\n return defaultValue;\n } else {\n return parsed;\n }\n } else {\n return defaultValue;\n }\n } else {\n return defaultValue;\n }\n }\n\n __checkBooleanAttribute(element, attributeName,defaultValue) {\n let bElement = !_.isNil(element) && _.isObject(element.attributes);\n let bAttribute = bElement && _.isString(attributeName) && (attributeName !== \"\") && !_.isNil(element.attributes[attributeName]);\n\n if(bAttribute) {\n let attributeValue = element.attributes[attributeName];\n if (attributeValue === \"true\") {\n return true;\n } else if (attributeValue === \"false\") {\n return false;\n } else {\n return defaultValue;\n }\n } else {\n return defaultValue;\n }\n }\n\n __checkEnumAttribute(element, attributeName,allowedEnumValues ,defaultValue) {\n let bElement = !_.isNil(element) && _.isObject(element.attributes);\n let bAttribute = bElement && _.isString(attributeName) && (attributeName !== \"\") && !_.isNil(element.attributes[attributeName]);\n\n if(bAttribute) {\n let attributeValue = element.attributes[attributeName];\n if(allowedEnumValues.includes(attributeValue)){\n return attributeValue;\n } else {\n return defaultValue;\n }\n } else {\n return defaultValue;\n }\n }\n\n __checkStringAttribute(element, attributeName, defaultValue) {\n let bElement = !_.isNil(element) && _.isObject(element.attributes);\n let bAttribute = bElement && _.isString(attributeName) && (attributeName !== \"\") && !_.isNil(element.attributes[attributeName]);\n\n if(bAttribute) {\n let attributeValue = element.attributes[attributeName];\n if(_.isString(attributeValue)){\n return attributeValue;\n } else {\n return defaultValue;\n }\n } else {\n return defaultValue;\n }\n }\n\n __applyNumberFormatAttribute(element, value) {\n let bElement = !_.isNil(element) && _.isObject(element.attributes);\n let bAttribute = bElement && !_.isNil(element.attributes.numberFormat) && !_.isNil(element.attributes.decimalSeparator) && !_.isNil(element.attributes.thousandSeparator);\n\n if (bAttribute) {\n return this.__format.formatDecimalV2(value, element.attributes.numberFormat, element.attributes.decimalSeparator, element.attributes.thousandSeparator);\n } else {\n return value;\n }\n }\n\n __createHeadingOrParagraphText(currentNode, text, style) {\n let result = { \"text\": text };\n\n let boldAttribute = this.__checkBooleanAttribute(currentNode, 'bold', null);\n let italicsAttribute = this.__checkBooleanAttribute(currentNode, 'italics', null);\n let alignmentAttribute = this.__checkEnumAttribute(currentNode, 'alignment', [\"left\", \"center\", \"right\"], null);\n\n if (_.isNil(boldAttribute) && _.isNil(italicsAttribute) && _.isNil(alignmentAttribute)) {\n result.style = style;\n } else {\n let styleJson = this.__definition.styles[style];\n\n if (!_.isNil(styleJson.fontSize)) {\n result.fontSize = styleJson.fontSize;\n }\n\n if (!_.isNil(styleJson.bold)) {\n result.bold = styleJson.bold;\n }\n\n if (!_.isNil(styleJson.italics)) {\n result.italics = styleJson.italics;\n }\n\n if (!_.isNil(styleJson.margin)) {\n result.margin = styleJson.margin;\n }\n\n if (!_.isNil(boldAttribute)) {\n result.bold = boldAttribute;\n }\n\n if (!_.isNil(italicsAttribute)) {\n result.italics = italicsAttribute;\n }\n\n if (!_.isNil(alignmentAttribute)) {\n result.alignment = alignmentAttribute;\n }\n }\n\n return result;\n }\n\n __createTableColumn(content, style, colSpan, rowSpan, alignment, bold, italics, cellId) {\n let bTextOnly = _.isNil(content.image) && _.isNil(style) && _.isNil(colSpan) && _.isNil(rowSpan)\n && _.isNil(alignment) && _.isNil(bold) && _.isNil(italics) && _.isNil(cellId);\n\n if (bTextOnly) {\n return content.text;\n }\n\n let column = {};\n\n //Image wins over text if both are defined.\n if (!_.isNil(content.image)) {\n column = content.image;\n } else {\n column.text = content.text;\n }\n\n if (!_.isNil(style)) {\n column.style = style;\n }\n if (!_.isNil(colSpan)) {\n column.colSpan = colSpan;\n }\n if (!_.isNil(rowSpan)) {\n column.rowSpan = rowSpan;\n }\n if (!_.isNil(alignment)) {\n column.alignment = alignment;\n }\n if (!_.isNil(bold)) {\n column.bold = bold;\n }\n if (!_.isNil(italics)) {\n column.italics = italics;\n }\n if (!_.isNil(cellId)) {\n column.id = cellId;\n }\n\n return column;\n }\n\n __getTableCellAttributes(thOrTdNode){\n let colSpanAttributeValue = this.__checkIntegerAttribute(thOrTdNode, 'colSpan', [], true, null);\n let rowSpanAttributeValue = this.__checkIntegerAttribute(thOrTdNode, 'rowSpan', [], true, null);\n let boldAttribute = this.__checkBooleanAttribute(thOrTdNode, 'bold', null);\n let italicsAttribute = this.__checkBooleanAttribute(thOrTdNode, 'italics', null);\n let alignmentAttribute = this.__checkEnumAttribute(thOrTdNode, 'alignment', [\"left\", \"center\", \"right\"], null);\n let cellId = this.__checkStringAttribute(thOrTdNode, 'id', null);\n\n return [colSpanAttributeValue, rowSpanAttributeValue, alignmentAttribute, boldAttribute, italicsAttribute, cellId];\n }\n\n __evaluateTableDefinitionRowBreak(tableNode, dynamicPageBreak) {\n let dontBreakRows = this.__checkBooleanAttribute(tableNode, \"dontBreakRows\", true);\n // deactivate automatic row breaks for tables requiring dynamic page breaks\n if (dynamicPageBreak) {\n dontBreakRows = false;\n }\n return dontBreakRows;\n }\n\n __evaluateTableDefinitionDynamicPageBreak(tableNode) {\n let automaticPageBreak = this.__automaticPageBreak; // => coming from PrintV2 action configuration\n let dynamicPageBreak = (automaticPageBreak && this.__checkBooleanAttribute(tableNode, \"dynamicPageBreak\", false));\n if (dynamicPageBreak) {\n this.__configurePdfDefinitionForDynamicPageBreak();\n }\n return dynamicPageBreak;\n }\n\n __configurePdfDefinitionForDynamicPageBreak() {\n if (!_.has(this.__definition, 'pageBreakBefore')) {\n _.assign(this.__definition, {\n pageBreakBefore: this.__calculatePageBreakBefore.bind(this)\n });\n this.__definition.dynamicPageBreak = true;\n }\n }\n\n __getTableDefinition(tableNode, settings) {\n if(_.isNil(settings)) {settings = {};}\n\n let dynamicPageBreak = this.__evaluateTableDefinitionDynamicPageBreak(tableNode);\n let dontBreakRows = this.__evaluateTableDefinitionRowBreak(tableNode, dynamicPageBreak);\n let pdfTableDefinition = {\n style: \"tableBody\",\n table: {\n dontBreakRows: dontBreakRows,\n headerRows: 0,\n body: [],\n widths: []\n }\n };\n if (dynamicPageBreak) {\n pdfTableDefinition.table.dynamicPageBreak = true;\n }\n\n if(!_.isNil(settings.layout)) {\n pdfTableDefinition.layout = settings.layout;\n }\n if(!_.isNil(tableNode.attributes) && !_.isNil(tableNode.attributes.tableLayout)){\n pdfTableDefinition.layout = tableNode.attributes.tableLayout;\n }\n\n let bNoWidths = false;\n let theadNode = _.find(tableNode.elements, {name: 'thead'});\n let tbodyNode = _.find(tableNode.elements, {name: 'tbody'});\n\n if(!_.isNil(theadNode)) {\n _.forEach(theadNode.elements, headerTrNode=> {\n let row = [];\n _.forEach(headerTrNode.elements, value => {\n let attributeValues = this.__getTableCellAttributes(value);\n\n if (pdfTableDefinition.table.headerRows === 0) {\n let widthAttributeValue = this.__checkIntegerAttribute(value, 'width', ['*', 'auto'], true, 'auto');\n pdfTableDefinition.table.widths.push(widthAttributeValue);\n }\n let content = this.__getThOrTdContent(value, settings);\n row.push(this.__createTableColumn(content, 'tableHeader', ...attributeValues));\n });\n\n pdfTableDefinition.table.body.push(row);\n pdfTableDefinition.table.headerRows += 1;\n });\n } else if(!_.isNil(tbodyNode)) {\n bNoWidths = true;\n } else {\n pdfTableDefinition.table.widths = ['auto'];\n pdfTableDefinition.table.body = [['']];\n\n return pdfTableDefinition;\n }\n\n if(!_.isNil(tbodyNode)) {\n _.forEach(tbodyNode.elements, tbodyTrNode=> {\n let row = [];\n _.forEach(tbodyTrNode.elements, value => {\n let attributeValues = this.__getTableCellAttributes(value);\n\n if ((bNoWidths === true)) {\n let widthAttributeValue = this.__checkIntegerAttribute(value, 'width', ['*', 'auto'], true, 'auto');\n pdfTableDefinition.table.widths.push(widthAttributeValue);\n }\n let content = this.__getThOrTdContent(value, settings);\n content.text = this.__applyNumberFormatAttribute(value, content.text);\n\n row.push(this.__createTableColumn(content, null, ...attributeValues));\n });\n\n bNoWidths = false;\n pdfTableDefinition.table.body.push(row);\n });\n }\n\n this.__checkSpansAndColumns(pdfTableDefinition);\n \n return pdfTableDefinition;\n }\n\n __addBody(definition, json) {\n\n _.forEach(json.elements, contractElement => {\n if(contractElement.name === 'table') {\n let tableDefintion = this.__getTableDefinition(contractElement);\n definition.content.push(tableDefintion);\n } else if (contractElement.name === 'h1') {\n let h1Defintion = this.__getHeadingDefinition(contractElement, STYLE_HEADING1);\n definition.content.push(h1Defintion);\n } else if (contractElement.name === 'h2') {\n let h2Defintion = this.__getHeadingDefinition(contractElement, STYLE_HEADING2);\n definition.content.push(h2Defintion);\n } else if (contractElement.name === 'p') {\n let paragraphDefintion = this.__getParagraphDefinition(contractElement, STYLE_PARAGRAPH);\n definition.content.push(paragraphDefintion);\n } else if (contractElement.name === 'img' || contractElement.name === 'signature') {\n let imageDefintion = this.__getImageDefinition(contractElement, true);\n definition.content.push(imageDefintion);\n }\n });\n\n }\n\n __addHeader(definition, json) {\n let headerNode = _.find(json.elements, {name:\"header\"});\n\n if(!_.isNil(headerNode)) {\n let imageNode = _.find(headerNode.elements, {name:\"img\"});\n let tableNode = _.find(headerNode.elements, {name:\"table\"});\n\n //The coverage report only works correctly when isWriteDataEnabled() returns true in the Unit Tests.\n definition.header = (currentPage/*, pageCount, pageSize*/) => {\n let imageDefinition = (!_.isNil(imageNode)) ? this.__getImageDefinition(imageNode, true) : null;\n let tableDefinition = (!_.isNil(tableNode)) ? this.__getTableDefinition(tableNode, {\"layout\": \"noBorders\", \"currentPage\": currentPage}) : null;\n\n if (!_.isNil(imageDefinition) && !_.isNil(tableDefinition)) {\n return [imageDefinition, tableDefinition];\n } else if (!_.isNil(tableDefinition)) {\n return tableDefinition;\n } else if (!_.isNil(imageDefinition)) {\n return imageDefinition;\n } else {\n return null;\n }\n };\n }\n }\n\n __addFooter(definition, json) {\n let footerNode = _.find(json.elements, {name:\"footer\"});\n if(!_.isNil(footerNode)) {\n let tableNode = _.find(footerNode.elements, {name:\"table\"});\n let bTableNode = !_.isNil(tableNode);\n\n //The coverage report only works correctly when isWriteDataEnabled() returns true in the Unit Tests.\n definition.footer = (currentPage/*, pageCount, pageSize*/) => {\n let tableDefinition = bTableNode ? this.__getTableDefinition(tableNode, {\"layout\": \"noBorders\", \"currentPage\":currentPage}) : null;\n return tableDefinition;\n };\n }\n }\n\n __addPrintFont(definition, printFont) {\n if (_.isObject(printFont)\n && (\"Regular\" in printFont)\n && (\"Bold\" in printFont)\n && (\"Italic\" in printFont)\n && (\"BoldItalic\" in printFont)) {\n definition.defaultStyle.font = \"PrintFont\";\n definition.printFont = printFont;\n }\n }\n\n __addDocumentMetadata(definition, documentProperties){\n definition.info = {};\n definition.info.creator = \"Consumer Goods Cloud\";\n definition.info.producer = \"Consumer Goods Cloud\";\n _.forEach(documentProperties, (value, key) => {\n definition.info[key] = value;\n });\n }\n\n __configureAutomaticPageBreak(reportLayout) {\n if(!_.isNil(reportLayout.attributes) && !_.isNil(reportLayout.attributes.automaticPageBreak)){\n this.__automaticPageBreak = reportLayout.attributes.automaticPageBreak;\n }\n }\n\n __addPageDimensionsOrientationMarginsWatermark(definition, reportLayout){\n if(!_.isNil(reportLayout.attributes) && !_.isNil(reportLayout.attributes.pageSize)){\n definition.pageSize = reportLayout.attributes.pageSize;\n }\n if(!_.isNil(reportLayout.attributes) && !_.isNil(reportLayout.attributes.watermark)){\n definition.watermark = {text: reportLayout.attributes.watermark, opacity:0.1, fontSize: 120};\n }\n if(!_.isNil(reportLayout.attributes) && !_.isNil(reportLayout.attributes.pageMargins)){\n definition.pageMargins = JSON.parse(reportLayout.attributes.pageMargins);\n }\n }\n\n __isLastMainRowOnPage(followingNodesOnPage) {\n let result = false;\n\n if (!_.isNil(followingNodesOnPage) && _.isArray(followingNodesOnPage)) {\n result = (followingNodesOnPage.length === 0) || !(_.some(followingNodesOnPage, y => {\n let tcid = TableCellIdentifier.fromString(y.id);\n return (tcid.isKnown() && tcid.isFirstMainRowCell());\n }));\n }\n\n return result;\n }\n\n __isFirstNodeOnNextPageFirstMainRowCell(nodesOnNextPage) {\n let result = false;\n\n if (!_.isNil(nodesOnNextPage) && _.isArray(nodesOnNextPage) && nodesOnNextPage.length > 0) {\n let firstNodeOnNextPage = _.first(nodesOnNextPage);\n let tcid = TableCellIdentifier.fromString(firstNodeOnNextPage.id);\n result = (tcid.isKnown() && tcid.isFirstMainRowCell());\n }\n\n return result;\n }\n\n __calculatePageBreakForParentChildRows(currentNode, followingNodesOnPage, nodesOnNextPage, previousNodesOnPage, tcidCurrentNode) {\n let doPageBreak = false;\n\n // dynamic pageBreak logic for parent-child rows\n if (!_.isNil(previousNodesOnPage) && _.isArray(previousNodesOnPage) && previousNodesOnPage.length > 0) {\n let previousNode = _.last(previousNodesOnPage);\n let tcidPreviousNode = TableCellIdentifier.fromString(previousNode.id);\n\n // => check if we are the first cell of a main row ...\n if (tcidCurrentNode.isFirstMainRowCell()) {\n\n if (!_.isNil(followingNodesOnPage) && _.isArray(followingNodesOnPage)) {\n\n let isCurrentNodeLastHeadOnPageX = this.__isLastMainRowOnPage(followingNodesOnPage);\n let isFirstNodeOnNextPageFirstMainRowCellX = this.__isFirstNodeOnNextPageFirstMainRowCell(nodesOnNextPage);\n let isPageBreakRelevant = (tcidPreviousNode.isKnown() && (tcidPreviousNode.isFirstMainRowCell() || tcidPreviousNode.isSubsequentMainRowCell() || tcidPreviousNode.isFirstCorrelatedRowCell() || tcidPreviousNode.isSubsequentCorrelatedRowCell()));\n\n doPageBreak = (isCurrentNodeLastHeadOnPageX && !isFirstNodeOnNextPageFirstMainRowCellX && isPageBreakRelevant);\n }\n\n } else if (tcidCurrentNode.isSubsequentMainRowCell()) {\n\n doPageBreak = (!tcidPreviousNode.isFirstMainRowCell() && !tcidPreviousNode.isSubsequentMainRowCell() || !(tcidCurrentNode.sharesMainRow(tcidPreviousNode)));\n }\n }\n\n return doPageBreak;\n }\n\n\n __calculatePageBreakForBrokenRows(currentNode, followingNodesOnPage, nodesOnNextPage, previousNodesOnPage, tcidCurrentNode) {\n let doPageBreak = false;\n\n // => check if we are the first cell of a row ...\n if (tcidCurrentNode.isFirstMainRowCell() || tcidCurrentNode.isFirstCorrelatedRowCell()) {\n // check for 'broken' row ...\n // => check if i am the last row\n let isLastRowOnPageX = (_.every(followingNodesOnPage, node => {\n let tcidNode = TableCellIdentifier.fromString(node.id);\n return !tcidNode.isKnown() || (tcidNode.isKnown() && tcidCurrentNode.sharesCorrelatedRow(tcidNode));\n }));\n\n if (isLastRowOnPageX) {\n // check if any cell of the current row extends over more than one page => pageBreak!\n // => check current cell (first cell of row)\n doPageBreak = (!_.isNil(currentNode.pageNumbers) && _.isArray(currentNode.pageNumbers) && currentNode.pageNumbers.length > 1);\n if (!doPageBreak) {\n // => check following cells on current page and cells on next page for page overlaps (other cells of row)\n doPageBreak = (_.some(followingNodesOnPage, node => {\n let tcidNode = TableCellIdentifier.fromString(node.id);\n if (tcidNode.isKnown() && tcidCurrentNode.sharesCorrelatedRow(tcidNode)) {\n return !_.isEqual(currentNode.pageNumbers, node.pageNumbers);\n }\n return false;\n }) || (_.some(nodesOnNextPage, node => {\n let tcidNode = TableCellIdentifier.fromString(node.id);\n if (tcidNode.isKnown() && tcidCurrentNode.sharesCorrelatedRow(tcidNode)) {\n return !_.isEqual(currentNode.pageNumbers, node.pageNumbers);\n }\n return false;\n })));\n }\n }\n } else if (tcidCurrentNode.isSubsequentMainRowCell() || tcidCurrentNode.isSubsequentCorrelatedRowCell()) {\n // => check other row cells ...\n if (!_.isNil(previousNodesOnPage) && _.isArray(previousNodesOnPage) && previousNodesOnPage.length > 0) {\n // check if last previous node is NOT precursor cell of current one => pageBreak!\n let previousNode = _.last(previousNodesOnPage);\n let tcidPreviousNode = TableCellIdentifier.fromString(previousNode.id);\n doPageBreak = !tcidCurrentNode.isPreviousCell(tcidPreviousNode);\n }\n }\n\n return doPageBreak;\n }\n\n __calculatePageBreakBefore(currentNode, followingNodesOnPage, nodesOnNextPage, previousNodesOnPage) {\n let doPageBreak = false;\n \n // looking for potential pageBreaks only makes sense if there are elements to be placed there (=> might require adaption for subtotals)\n if (!_.isNil(nodesOnNextPage) && _.isArray(nodesOnNextPage) && nodesOnNextPage.length > 0) {\n\n // get table cell identifier\n let tcidCurrentNode = TableCellIdentifier.fromString(currentNode.id);\n if (!_.isNil(tcidCurrentNode) && tcidCurrentNode.isKnown()) {\n\n // check for dynamic pageBreak of parent-child rows\n doPageBreak = this.__calculatePageBreakForParentChildRows(currentNode, followingNodesOnPage, nodesOnNextPage, previousNodesOnPage, tcidCurrentNode); \n if (!doPageBreak) { \n // check for dynamic pageBreak of 'broken' row\n doPageBreak = this.__calculatePageBreakForBrokenRows(currentNode, followingNodesOnPage, nodesOnNextPage, previousNodesOnPage, tcidCurrentNode); \n }\n \n if (doPageBreak && !_.isUndefined(this.__definition.dynamicPageBreak) && this.__definition.dynamicPageBreak) { \n if (tcidCurrentNode.isFirstMainRowCell() || tcidCurrentNode.isFirstCorrelatedRowCell()) {\n // cache dynamic pageBreak to turn them into manual ones during the second run ...\n this.__definition.dynamicPageBreakData.push(tcidCurrentNode.toString()); \n } else {\n doPageBreak = false;\n }\n }\n\n }\n } \n\n return doPageBreak;\n }\n\n __createPdfDocument(pdfDefinition, pdfCreationFunction) {\n // clone pdf definition if applicable ...\n let pdfDefinitionCopy = null;\n if (!_.isNil(pdfDefinition) && !_.isUndefined(pdfDefinition.dynamicPageBreak) && pdfDefinition.dynamicPageBreak &&\n !_.isNil(pdfCreationFunction) && _.isFunction(pdfCreationFunction)) {\n // init empty dynamicPageBreakData ...\n _.assign(pdfDefinition, {\n dynamicPageBreakData: []\n });\n\n pdfDefinitionCopy = _.cloneDeep(pdfDefinition);\n // skip header / footer for initial layouting and move them to final layouting\n if (!_.isUndefined(pdfDefinition.header)) {\n let headerFunction = pdfDefinition.header;\n _.assign(pdfDefinitionCopy, {\n 'header': headerFunction\n });\n _.unset(pdfDefinition, 'header');\n }\n if (!_.isUndefined(pdfDefinition.footer)) {\n let footerFunction = pdfDefinition.footer;\n _.assign(pdfDefinitionCopy, {\n 'footer': footerFunction\n });\n _.unset(pdfDefinition, 'footer');\n }\n // remove dynamic pageBreak logic\n _.unset(pdfDefinitionCopy, 'pageBreakBefore');\n }\n\n // set pdf definition to be layouted ...\n this.__definition = pdfDefinition;\n\n // exec pdfCreation function ...\n pdfCreationFunction.apply(this, [pdfDefinition]);\n\n return pdfDefinitionCopy;\n }\n\n __createFinalPdfDocument(pdfDefinition, pdfDefinitionCopy, pdfCreationFunction) {\n // perform pageBreak magic ...\n if (!_.isNil(pdfDefinition) && !_.isUndefined(pdfDefinition.dynamicPageBreak) && pdfDefinition.dynamicPageBreak &&\n !_.isUndefined(pdfDefinition.dynamicPageBreakData) && _.isArray(pdfDefinition.dynamicPageBreakData) &&\n !_.isNil(pdfDefinitionCopy) && !_.isUndefined(pdfDefinitionCopy.dynamicPageBreak) && pdfDefinitionCopy.dynamicPageBreak &&\n !_.isNil(pdfCreationFunction) && _.isFunction(pdfCreationFunction)) {\n\n // transfer dynamicPageBreakData from pdf definition to its copy\n pdfDefinitionCopy.dynamicPageBreakData = pdfDefinition.dynamicPageBreakData;\n\n this.__applyPageBreakData(pdfDefinitionCopy);\n\n // set pdf definition to be layouted ...\n this.__definition = pdfDefinitionCopy;\n\n // exec pdfCreation function ...\n pdfCreationFunction.apply(this, [pdfDefinitionCopy]);\n }\n }\n\n toPdfDefinition(json/*, format*/) {\n this.__initializePdfDefinition();\n this.__addPrintFont(this.__definition, json.printFont);\n this.__addDocumentMetadata(this.__definition, json.documentProperties);\n let reportLayout = json.reportLayout;\n this.__configureAutomaticPageBreak(reportLayout);\n this.__addPageDimensionsOrientationMarginsWatermark(this.__definition, reportLayout);\n this.__addHeader(this.__definition, reportLayout);\n this.__addBody(this.__definition, reportLayout);\n this.__addFooter(this.__definition,reportLayout);\n return this.__definition;\n }\n\n writeToStream(pdfDefinition, stream) {\n // setup pdf creator ...\n let printer = new PdfPrinter(ServerFonts);\n let pdfDoc = null; \n let pdfCreatorFunction = (definition) => {\n printer = new PdfPrinter(ServerFonts);\n pdfDoc = printer.createPdfKitDocument(definition, {\n tableLayouts: TableLayouts\n });\n };\n\n // create pdf and prepare for recreation if applicable ...\n let pdfDefinitionCopy = this.__createPdfDocument(pdfDefinition, pdfCreatorFunction);\n\n // recreate pdf if applicable ...\n this.__createFinalPdfDocument(pdfDefinition, pdfDefinitionCopy, pdfCreatorFunction);\n\n pdfDoc.pipe(stream);\n pdfDoc.end();\n\n return (pdfDefinitionCopy || pdfDefinition);\n }\n\n async __createPdfDocumentAsync(pdfDefinition) {\n return new Promise((resolve, reject) => {\n try {\n \n // clone pdf definition if applicable ...\n let pdfDefinitionCopy = null;\n if (!_.isNil(pdfDefinition) && !_.isUndefined(pdfDefinition.dynamicPageBreak) && pdfDefinition.dynamicPageBreak) {\n // init empty dynamicPageBreakData ...\n _.assign(pdfDefinition, {\n dynamicPageBreakData: []\n });\n\n pdfDefinitionCopy = _.cloneDeep(pdfDefinition);\n // skip header / footer for initial layouting and move them to final layouting\n if (!_.isUndefined(pdfDefinition.header)) {\n let headerFunction = pdfDefinition.header;\n _.assign(pdfDefinitionCopy, {\n 'header': headerFunction\n });\n _.unset(pdfDefinition, 'header');\n }\n if (!_.isUndefined(pdfDefinition.footer)) {\n let footerFunction = pdfDefinition.footer;\n _.assign(pdfDefinitionCopy, {\n 'footer': footerFunction\n });\n _.unset(pdfDefinition, 'footer');\n }\n // remove dynamic pageBreak logic\n _.unset(pdfDefinitionCopy, 'pageBreakBefore');\n }\n\n // set pdf definition to be layouted ...\n this.__definition = pdfDefinition; \n \n resolve(pdfDefinitionCopy);\n } catch (error) {\n reject(error);\n }\n });\n }\n\n async __createFinalPdfDocumentAsync(pdfDefinition, pdfDefinitionCopy) {\n return new Promise((resolve, reject) => {\n try {\n // perform pageBreak magic ...\n if (!_.isNil(pdfDefinition) && !_.isUndefined(pdfDefinition.dynamicPageBreak) && pdfDefinition.dynamicPageBreak &&\n !_.isUndefined(pdfDefinition.dynamicPageBreakData) && _.isArray(pdfDefinition.dynamicPageBreakData) &&\n !_.isNil(pdfDefinitionCopy) && !_.isUndefined(pdfDefinitionCopy.dynamicPageBreak) && pdfDefinitionCopy.dynamicPageBreak) {\n\n // transfer dynamicPageBreakData from pdf definition to its copy\n pdfDefinitionCopy.dynamicPageBreakData = pdfDefinition.dynamicPageBreakData;\n\n this.__applyPageBreakData(pdfDefinitionCopy);\n\n // set pdf definition to be layouted ...\n this.__definition = pdfDefinitionCopy; \n }\n resolve();\n } catch (error) {\n reject(error);\n }\n }); \n }\n\n async __getPdfDataAsync(type, pdfDefinition, previousResult = null) {\n return new Promise((resolve, reject) => {\n try {\n if (_.isNil(pdfDefinition) && !_.isNil(previousResult)) {\n resolve(previousResult);\n } else {\n let pdfDocGenerator = null;\n if (pdfDefinition.defaultStyle.font !== \"PrintFont\") {\n pdfDocGenerator = this.__pdfMake.createPdf(pdfDefinition, TableLayouts, BrowserFonts, BrowserFontsVfs.pdfMake.vfs);\n }\n else {\n pdfDocGenerator = this.__pdfMake.createPdf(pdfDefinition, TableLayouts, BrowserFonts, pdfDefinition.printFont);\n }\n \n switch (type) {\n case EXPORT_TYPE.BASE_64:\n pdfDocGenerator.getBase64((data) => {\n resolve(data);\n });\n break;\n\n case EXPORT_TYPE.BLOB:\n pdfDocGenerator.getBlob((blob) => {\n resolve(blob);\n });\n break;\n\n case EXPORT_TYPE.DATA_URL:\n pdfDocGenerator.getDataUrl((dataUrl) => {\n resolve(dataUrl);\n });\n break;\n\n default: \n throw new Error('Unknown export type: ' + type ); \n }\n }\n\n } catch (error) {\n reject(error);\n }\n });\n }\n\n async toBase64(pdfDefinition) {\n // hint: works only in browser avoid calling it in node.js\n let pdfDefinitionCopy = null;\n let firstResult = null; \n \n return this.__createPdfDocumentAsync(pdfDefinition).then((pdfDef) => {\n pdfDefinitionCopy = pdfDef;\n return this.__getPdfDataAsync(EXPORT_TYPE.BASE_64, pdfDefinition);\n }).then((pdfData) => {\n firstResult = pdfData;\n return this.__createFinalPdfDocumentAsync(pdfDefinition, pdfDefinitionCopy);\n }).then(() => {\n return this.__getPdfDataAsync(EXPORT_TYPE.BASE_64, pdfDefinitionCopy, firstResult); \n });\n \n }\n\n async toBlob(pdfDefinition) {\n // hint: works only in browser avoid calling it in node.js\n let pdfDefinitionCopy = null;\n let firstResult = null; \n \n return this.__createPdfDocumentAsync(pdfDefinition).then((pdfDef) => {\n pdfDefinitionCopy = pdfDef;\n return this.__getPdfDataAsync(EXPORT_TYPE.BLOB, pdfDefinition);\n }).then((pdfData) => {\n firstResult = pdfData;\n return this.__createFinalPdfDocumentAsync(pdfDefinition, pdfDefinitionCopy);\n }).then(() => {\n return this.__getPdfDataAsync(EXPORT_TYPE.BLOB, pdfDefinitionCopy, firstResult); \n });\n }\n \n async toDataUrl(pdfDefinition) {\n // hint: works only in browser avoid calling it in node.js\n let pdfDefinitionCopy = null;\n let firstResult = null; \n \n return this.__createPdfDocumentAsync(pdfDefinition).then((pdfDef) => {\n pdfDefinitionCopy = pdfDef;\n return this.__getPdfDataAsync(EXPORT_TYPE.DATA_URL, pdfDefinition);\n }).then((pdfData) => {\n firstResult = pdfData;\n return this.__createFinalPdfDocumentAsync(pdfDefinition, pdfDefinitionCopy);\n }).then(() => {\n return this.__getPdfDataAsync(EXPORT_TYPE.DATA_URL, pdfDefinitionCopy, firstResult); \n });\n \n }\n\n static isValidFormat(format) {\n let supportedFormats = ['A3', 'A4', 'A5', 'Legal', 'Letter', 'Tabloid'];\n return supportedFormats.includes(format);\n }\n\n}\n\n\nmodule.exports = PdfConverter;\n\n\n//# sourceURL=webpack://__FWPrinting/./src/pdfConverterClass.js?");
471
+ eval("/*\n * FILE_HEADER\n */\n\n\nconst _ = __webpack_require__(/*! lodash */ \"./node_modules/lodash/lodash.js\");\nconst PdfPrinter = __webpack_require__(/*! pdfmake */ \"./node_modules/pdfmake/build/pdfmake.js\");\nconst Format = __webpack_require__(/*! ./formatClass */ \"./src/formatClass.js\");\nconst TableCellIdentifier = __webpack_require__(/*! ./tableCellIdentifier */ \"./src/tableCellIdentifier.js\");\n\n// required for webpack include (browser impl), used in conjunction with BrowserFonts definition\nconst BrowserFontsVfs = __webpack_require__(/*! pdfmake/build/vfs_fonts.js */ \"./node_modules/pdfmake/build/vfs_fonts.js\");\n\n// => use 'Roboto' font (pdfMake default) due to licensing (Apache 2.0)\n// https://fonts.google.com/specimen/Roboto || https://en.wikipedia.org/wiki/Roboto\nconst ServerFonts = {\n Roboto: {\n normal: './fonts/Roboto-Regular.ttf',\n bold: './fonts/Roboto-Medium.ttf',\n italics: './fonts/Roboto-Italic.ttf',\n bolditalics: './fonts/Roboto-MediumItalic.ttf'\n }\n};\n\nconst BrowserFonts = {\n Roboto: {\n normal: 'Roboto-Regular.ttf',\n bold: 'Roboto-Medium.ttf',\n italics: 'Roboto-Italic.ttf',\n bolditalics: 'Roboto-MediumItalic.ttf'\n },\n PrintFont: {\n normal: 'Regular',\n bold: 'Bold',\n italics: 'Italic',\n bolditalics: 'BoldItalic'\n }\n};\n\nconst TableLayouts = {\n lightHorizontalLinesMainItemsOnly: {\n hLineWidth: function (i, node) {\n // no frame for the table\n if (i === 0 || i === node.table.body.length) {\n return 0;\n }\n // bold seperator between header and body\n if (i === node.table.headerRows) {\n return 2;\n }\n // get first cell id for row ...\n let row = node.table.body[i];\n if (!_.isNil(row)) {\n let cellId = null;\n _.forEach(row, cell =>{\n if(_.has(cell, 'id')) {\n cellId = cell.id;\n return false;\n }\n });\n // seperator for between main rows (+ their child rows)\n let tcid = TableCellIdentifier.fromString(cellId);\n if (!_.isNil(tcid)) {\n if (tcid.isKnown() && tcid.belongsToMainRow()) {\n // seperator between main rows\n return 1;\n } else if (!tcid.isKnown()) {\n // seperator for 'unknown row'\n return 1;\n }\n }\n }\n // no seperator for all other cases, e.g. child rows\n return 0;\n },\n vLineWidth: function () {\n return 0;\n },\n hLineColor: function (i, node) {\n return i === node.table.headerRows ? 'black' : 'gray';\n }\n }\n};\n\nconst STYLE_HEADING1 = \"heading1\";\nconst STYLE_HEADING2 = \"heading2\";\nconst STYLE_PARAGRAPH = \"paragraph\";\n\nconst EXPORT_TYPE = {\n \"BASE_64\" : \"BASE_64\",\n \"DATA_URL\" : \"DATA_URL\",\n \"BLOB\" : \"BLOB\"\n};\nObject.freeze(EXPORT_TYPE);\n\nclass PdfConverter {\n constructor() {\n this.__pdfMake = null;\n if(typeof pdfMake !== \"undefined\")\n {\n this.__pdfMake = pdfMake;\n }\n\n this.__format = new Format();\n this.__pdfHeight = null;\n }\n\n __applyPageBreakData(pdfDefinition) {\n if (!_.isUndefined(pdfDefinition.dynamicPageBreak) && pdfDefinition.dynamicPageBreak && \n !_.isUndefined(pdfDefinition.dynamicPageBreakData) && _.isArray(pdfDefinition.dynamicPageBreakData) && pdfDefinition.dynamicPageBreakData.length > 0) {\n // let table = pdfDefinition.content[0].table;\n let dynamicPageBreakData = pdfDefinition.dynamicPageBreakData;\n \n // handle tables in body\n let tables = _.filter(pdfDefinition.content, {style: 'tableBody'});\n this.__applyPageBreakDataToTables(tables, dynamicPageBreakData);\n }\n } \n\n __applyPageBreakDataToTables(tables, dynamicPageBreakData) {\n\n if (!_.isNil(tables) && _.isArray(tables) && tables.length > 0 && !_.isNil(dynamicPageBreakData)) {\n for (let i = 0; i < tables.length; i++) {\n // get table\n let table = tables[i].table;\n if (!_.isNil(table) && !_.isUndefined(table.dynamicPageBreak) && table.dynamicPageBreak) {\n // loop rows\n let row = null;\n let cell = null;\n let breakRow = false;\n for (let j = 0; j < table.body.length; j++) { \n row = table.body[j];\n breakRow = false;\n // loop columns\n for (let k = 0; k < row.length; k++) {\n cell = row[k];\n // apply manual pageBreaks instead of dynamic ones\n if (!breakRow && _.has(cell, 'id')) {\n breakRow = _.includes(dynamicPageBreakData, cell.id);\n if (breakRow) {\n cell.pageBreak = 'before';\n } \n } else if (breakRow && _.has(cell, 'id')) {\n cell.pageBreak = 'before';\n }\n }\n }\n }\n }\n }\n\n }\n \n __initializePdfDefinition() {\n this.__definition = {\n \"content\": [],\n pageSize: 'A4',\n pageMargins: [ 40, 60, 40, 60 ],\n defaultStyle: {\n font: 'Roboto', //'Helvetica'\n },\n styles: {\n tableBody: {\n fontSize: 10,\n margin: [0, 5, 0, 15]\n },\n tableHeader: {\n fontSize: 10,\n bold: true\n },\n heading1: {\n fontSize: 18,\n bold: true,\n margin: [0, 0, 0, 10]\n },\n heading2: {\n fontSize: 14,\n bold: true,\n margin: [0, 10, 0, 5]\n },\n paragraph: {\n fontSize: 10,\n bold: false,\n italics: false\n }\n }\n };\n this.__automaticPageBreak = false;\n }\n\n __getThOrTdContent(thTdNode, settings) {\n let result = {};\n let text = \"\";\n\n if(!_.isNil(thTdNode.elements)){\n _.forEach(thTdNode.elements, childElement => {\n if(childElement.type === \"text\") {\n text = text + childElement.text;\n } else if (childElement.type === \"element\" && childElement.name === \"pageNumber\" && !_.isNil(settings.currentPage)) {\n text = text + settings.currentPage;\n } else if (childElement.type === \"element\" && childElement.name === \"img\") {\n result.image = this.__getImageDefinition(childElement, false);\n }\n });\n }\n result.text = text;\n\n return result;\n }\n\n __getHeadingDefinition(headingNode, headingStyle) {\n return this.__createHeadingOrParagraphText(headingNode, headingNode.elements[0].text, headingStyle);\n }\n\n __getParagraphDefinition(paragraphNode, paragraphStyle) {\n let text = '';\n if (paragraphNode.elements) {\n text = paragraphNode.elements[0].text;\n }\n return this.__createHeadingOrParagraphText(paragraphNode, text, paragraphStyle);\n }\n\n __getImageDefinition(imageNode, useAlignment) {\n let img = {};\n\n if (!_.isNil(imageNode)){\n let atr = imageNode.attributes;\n let imageId = atr.id;\n let mimeType = atr.mimeType;\n\n if (!_.isNil(imageId) && this.__isImageCached(imageId)) {\n // => png / jpeg image already in cache => simply (re)use it ...\n img = {image: imageId};\n\n } else {\n\n if (mimeType === \"image/svg+xml\") {\n // => svg image handling (vector graphics)\n let src = atr.src.split(\",\");\n let data = src[1];\n let txt;\n\n if ((typeof window === 'object') && (typeof window.atob === 'function')) {\n // we do expect an utf8 string\n txt = decodeURIComponent(encodeURIComponent(window.atob(data)));\n } else {\n let buf = Buffer.from(data, 'base64');\n txt = buf.toString('utf8');\n }\n img = {svg: txt};\n\n } else {\n // => png / jpeg image handling (raster graphics)\n // add image to cache\n this.__addImageToCache(imageId, atr.src);\n img = {image: imageId}; \n\n }\n } \n\n if (!_.isNil(atr.width)) {\n img.width = parseInt(atr.width, 10);\n }\n if (!_.isNil(atr.height)) {\n img.height = parseInt(atr.height, 10);\n }\n if (!_.isNil(atr.fit)) {\n let fit = atr.fit.split(',');\n let w = parseInt(fit[0], 10);\n let h = parseInt(fit[1], 10);\n img.fit = [w,h];\n }\n\n if (!_.isNil(atr.alignment) && (true === useAlignment)) {\n let alignmentAttribute = this.__checkEnumAttribute(imageNode, 'alignment', [\"left\", \"center\", \"right\"], null);\n\n if (!_.isNil(alignmentAttribute)) {\n img.alignment = alignmentAttribute;\n }\n }\n }\n\n return img;\n }\n\n __addImageToCache(imageId, imageData) {\n // init image cache if required\n if (!_.has(this.__definition, 'images')) { \n _.assign(this.__definition, {\n images: {}\n });\n }\n\n // add image to cache\n if (!_.has(this.__definition.images, imageId)) {\n this.__definition.images[imageId] = imageData;\n }\n }\n\n __isImageCached(imageId) {\n return (_.has(this.__definition, 'images') && _.has(this.__definition.images, imageId));\n }\n\n __checkSpansAndColumns(pdfTableDefinition) {\n let rows = 0;\n let columns = 0;\n\n let rowCount = pdfTableDefinition.table.body.length;\n let columnCount = pdfTableDefinition.table.widths.length;\n\n for (rows=0; rows<rowCount; rows++) {\n let row = pdfTableDefinition.table.body[rows];\n\n if (row.length > columnCount) {\n row.length = columnCount;\n } else if (row.length < columnCount) {\n do {\n row.push(\"\");\n } while(row.length < columnCount);\n }\n\n let maxRowSpan = rowCount-rows;\n\n for (columns=0; columns<columnCount; columns++) {\n let column = row[columns];\n let maxColSpan = columnCount-columns;\n\n if (!_.isString(column)) {\n if (!_.isNil(column[\"colSpan\"])) {\n if (column.colSpan > maxColSpan) {\n column.colSpan = maxColSpan;\n }\n if (column.colSpan < 2) {\n delete column.colSpan;\n }\n if ((Object.keys(column).length === 1) && !_.isNil(column[\"text\"])) {\n row[columns] = column.text;\n }\n }\n if (!_.isNil(column[\"rowSpan\"])) {\n if (column.rowSpan > maxRowSpan) {\n column.rowSpan = maxRowSpan;\n }\n if (column.rowSpan < 2) {\n delete column.rowSpan;\n }\n if ((Object.keys(column).length === 1) && !_.isNil(column[\"text\"])) {\n row[columns] = column.text;\n }\n }\n }\n }\n }\n }\n\n __checkIntegerAttribute(element, attributeName, allowedStrings, onlyPositiveNumbers, defaultValue) {\n let bElement = !_.isNil(element) && _.isObject(element.attributes);\n let bAttribute = bElement && _.isString(attributeName) && (attributeName !== \"\") && !_.isNil(element.attributes[attributeName]);\n let bAllowedStrings = !_.isNil(allowedStrings) && _.isArray(allowedStrings) && (allowedStrings.length > 0);\n let bPositiveNumbers = !_.isNil(onlyPositiveNumbers) && _.isBoolean(onlyPositiveNumbers) && (onlyPositiveNumbers === true);\n\n if (bAttribute) {\n let attribute = element.attributes[attributeName];\n let i = 0;\n\n if (bAllowedStrings && _.isString(attribute)){\n //the width can be given as a percentage only if the layout is 3-inch endless printer i.e, the height is auto\n if(this.__pdfHeight === 'auto' && (/^\\d+(\\.\\d+)?%$/).test(attribute)){\n return attribute;\n }\n for (i=0; i<allowedStrings.length; i++) {\n if (attribute === allowedStrings[i]) {\n return attribute;\n }\n }\n }\n\n let parsed = parseInt(attribute, 10);\n\n if(!isNaN(parsed)) {\n if (bPositiveNumbers && (parsed < 0))\n {\n return defaultValue;\n } else {\n return parsed;\n }\n } else {\n return defaultValue;\n }\n } else {\n return defaultValue;\n }\n }\n\n __checkBooleanAttribute(element, attributeName,defaultValue) {\n let bElement = !_.isNil(element) && _.isObject(element.attributes);\n let bAttribute = bElement && _.isString(attributeName) && (attributeName !== \"\") && !_.isNil(element.attributes[attributeName]);\n\n if(bAttribute) {\n let attributeValue = element.attributes[attributeName];\n if (attributeValue === \"true\") {\n return true;\n } else if (attributeValue === \"false\") {\n return false;\n } else {\n return defaultValue;\n }\n } else {\n return defaultValue;\n }\n }\n\n __checkEnumAttribute(element, attributeName,allowedEnumValues ,defaultValue) {\n let bElement = !_.isNil(element) && _.isObject(element.attributes);\n let bAttribute = bElement && _.isString(attributeName) && (attributeName !== \"\") && !_.isNil(element.attributes[attributeName]);\n\n if(bAttribute) {\n let attributeValue = element.attributes[attributeName];\n if(allowedEnumValues.includes(attributeValue)){\n return attributeValue;\n } else {\n return defaultValue;\n }\n } else {\n return defaultValue;\n }\n }\n\n __checkStringAttribute(element, attributeName, defaultValue) {\n let bElement = !_.isNil(element) && _.isObject(element.attributes);\n let bAttribute = bElement && _.isString(attributeName) && (attributeName !== \"\") && !_.isNil(element.attributes[attributeName]);\n\n if(bAttribute) {\n let attributeValue = element.attributes[attributeName];\n if(_.isString(attributeValue)){\n return attributeValue;\n } else {\n return defaultValue;\n }\n } else {\n return defaultValue;\n }\n }\n\n __applyNumberFormatAttribute(element, value) {\n let bElement = !_.isNil(element) && _.isObject(element.attributes);\n let bAttribute = bElement && !_.isNil(element.attributes.numberFormat) && !_.isNil(element.attributes.decimalSeparator) && !_.isNil(element.attributes.thousandSeparator);\n\n if (bAttribute) {\n return this.__format.formatDecimalV2(value, element.attributes.numberFormat, element.attributes.decimalSeparator, element.attributes.thousandSeparator);\n } else {\n return value;\n }\n }\n\n __createHeadingOrParagraphText(currentNode, text, style) {\n let result = { \"text\": text };\n\n let boldAttribute = this.__checkBooleanAttribute(currentNode, 'bold', null);\n let italicsAttribute = this.__checkBooleanAttribute(currentNode, 'italics', null);\n let alignmentAttribute = this.__checkEnumAttribute(currentNode, 'alignment', [\"left\", \"center\", \"right\"], null);\n\n if (_.isNil(boldAttribute) && _.isNil(italicsAttribute) && _.isNil(alignmentAttribute)) {\n result.style = style;\n } else {\n let styleJson = this.__definition.styles[style];\n\n if (!_.isNil(styleJson.fontSize)) {\n result.fontSize = styleJson.fontSize;\n }\n\n if (!_.isNil(styleJson.bold)) {\n result.bold = styleJson.bold;\n }\n\n if (!_.isNil(styleJson.italics)) {\n result.italics = styleJson.italics;\n }\n\n if (!_.isNil(styleJson.margin)) {\n result.margin = styleJson.margin;\n }\n\n if (!_.isNil(boldAttribute)) {\n result.bold = boldAttribute;\n }\n\n if (!_.isNil(italicsAttribute)) {\n result.italics = italicsAttribute;\n }\n\n if (!_.isNil(alignmentAttribute)) {\n result.alignment = alignmentAttribute;\n }\n }\n\n return result;\n }\n\n __createTableColumn(content, style, colSpan, rowSpan, alignment, bold, italics, cellId) {\n let bTextOnly = _.isNil(content.image) && _.isNil(style) && _.isNil(colSpan) && _.isNil(rowSpan)\n && _.isNil(alignment) && _.isNil(bold) && _.isNil(italics) && _.isNil(cellId);\n\n if (bTextOnly) {\n return content.text;\n }\n\n let column = {};\n\n //Image wins over text if both are defined.\n if (!_.isNil(content.image)) {\n column = content.image;\n } else {\n column.text = content.text;\n }\n\n if (!_.isNil(style)) {\n column.style = style;\n }\n if (!_.isNil(colSpan)) {\n column.colSpan = colSpan;\n }\n if (!_.isNil(rowSpan)) {\n column.rowSpan = rowSpan;\n }\n if (!_.isNil(alignment)) {\n column.alignment = alignment;\n }\n if (!_.isNil(bold)) {\n column.bold = bold;\n }\n if (!_.isNil(italics)) {\n column.italics = italics;\n }\n if (!_.isNil(cellId)) {\n column.id = cellId;\n }\n\n return column;\n }\n\n __getTableCellAttributes(thOrTdNode){\n let colSpanAttributeValue = this.__checkIntegerAttribute(thOrTdNode, 'colSpan', [], true, null);\n let rowSpanAttributeValue = this.__checkIntegerAttribute(thOrTdNode, 'rowSpan', [], true, null);\n let boldAttribute = this.__checkBooleanAttribute(thOrTdNode, 'bold', null);\n let italicsAttribute = this.__checkBooleanAttribute(thOrTdNode, 'italics', null);\n let alignmentAttribute = this.__checkEnumAttribute(thOrTdNode, 'alignment', [\"left\", \"center\", \"right\"], null);\n let cellId = this.__checkStringAttribute(thOrTdNode, 'id', null);\n\n return [colSpanAttributeValue, rowSpanAttributeValue, alignmentAttribute, boldAttribute, italicsAttribute, cellId];\n }\n\n __evaluateTableDefinitionRowBreak(tableNode, dynamicPageBreak) {\n let dontBreakRows = this.__checkBooleanAttribute(tableNode, \"dontBreakRows\", true);\n // deactivate automatic row breaks for tables requiring dynamic page breaks\n if (dynamicPageBreak) {\n dontBreakRows = false;\n }\n return dontBreakRows;\n }\n\n __evaluateTableDefinitionDynamicPageBreak(tableNode) {\n let automaticPageBreak = this.__automaticPageBreak; // => coming from PrintV2 action configuration\n let dynamicPageBreak = (automaticPageBreak && this.__checkBooleanAttribute(tableNode, \"dynamicPageBreak\", false));\n if (dynamicPageBreak) {\n this.__configurePdfDefinitionForDynamicPageBreak();\n }\n return dynamicPageBreak;\n }\n\n __configurePdfDefinitionForDynamicPageBreak() {\n if (!_.has(this.__definition, 'pageBreakBefore')) {\n _.assign(this.__definition, {\n pageBreakBefore: this.__calculatePageBreakBefore.bind(this)\n });\n this.__definition.dynamicPageBreak = true;\n }\n }\n\n __getTableDefinition(tableNode, settings) {\n if(_.isNil(settings)) {settings = {};}\n\n let dynamicPageBreak = this.__evaluateTableDefinitionDynamicPageBreak(tableNode);\n let dontBreakRows = this.__evaluateTableDefinitionRowBreak(tableNode, dynamicPageBreak);\n let pdfTableDefinition = {\n style: \"tableBody\",\n table: {\n dontBreakRows: dontBreakRows,\n headerRows: 0,\n body: [],\n widths: []\n }\n };\n if (dynamicPageBreak) {\n pdfTableDefinition.table.dynamicPageBreak = true;\n }\n\n if(!_.isNil(settings.layout)) {\n pdfTableDefinition.layout = settings.layout;\n }\n if(!_.isNil(tableNode.attributes) && !_.isNil(tableNode.attributes.tableLayout)){\n pdfTableDefinition.layout = tableNode.attributes.tableLayout;\n }\n\n let bNoWidths = false;\n let theadNode = _.find(tableNode.elements, {name: 'thead'});\n let tbodyNode = _.find(tableNode.elements, {name: 'tbody'});\n\n if(!_.isNil(theadNode)) {\n _.forEach(theadNode.elements, headerTrNode=> {\n let row = [];\n _.forEach(headerTrNode.elements, value => {\n let attributeValues = this.__getTableCellAttributes(value);\n\n if (pdfTableDefinition.table.headerRows === 0) {\n let widthAttributeValue = this.__checkIntegerAttribute(value, 'width', ['*', 'auto'], true, 'auto');\n pdfTableDefinition.table.widths.push(widthAttributeValue);\n }\n let content = this.__getThOrTdContent(value, settings);\n row.push(this.__createTableColumn(content, 'tableHeader', ...attributeValues));\n });\n\n pdfTableDefinition.table.body.push(row);\n pdfTableDefinition.table.headerRows += 1;\n });\n } else if(!_.isNil(tbodyNode)) {\n bNoWidths = true;\n } else {\n pdfTableDefinition.table.widths = ['auto'];\n pdfTableDefinition.table.body = [['']];\n\n return pdfTableDefinition;\n }\n\n if(!_.isNil(tbodyNode)) {\n _.forEach(tbodyNode.elements, tbodyTrNode=> {\n let row = [];\n _.forEach(tbodyTrNode.elements, value => {\n let attributeValues = this.__getTableCellAttributes(value);\n\n if ((bNoWidths === true)) {\n let widthAttributeValue = this.__checkIntegerAttribute(value, 'width', ['*', 'auto'], true, 'auto');\n pdfTableDefinition.table.widths.push(widthAttributeValue);\n }\n let content = this.__getThOrTdContent(value, settings);\n content.text = this.__applyNumberFormatAttribute(value, content.text);\n\n row.push(this.__createTableColumn(content, null, ...attributeValues));\n });\n\n bNoWidths = false;\n pdfTableDefinition.table.body.push(row);\n });\n }\n\n this.__checkSpansAndColumns(pdfTableDefinition);\n \n return pdfTableDefinition;\n }\n\n __addBody(definition, json) {\n\n _.forEach(json.elements, contractElement => {\n if(contractElement.name === 'table') {\n let tableDefintion = this.__getTableDefinition(contractElement);\n definition.content.push(tableDefintion);\n } else if (contractElement.name === 'h1') {\n let h1Defintion = this.__getHeadingDefinition(contractElement, STYLE_HEADING1);\n definition.content.push(h1Defintion);\n } else if (contractElement.name === 'h2') {\n let h2Defintion = this.__getHeadingDefinition(contractElement, STYLE_HEADING2);\n definition.content.push(h2Defintion);\n } else if (contractElement.name === 'p') {\n let paragraphDefintion = this.__getParagraphDefinition(contractElement, STYLE_PARAGRAPH);\n definition.content.push(paragraphDefintion);\n } else if (contractElement.name === 'img' || contractElement.name === 'signature') {\n let imageDefintion = this.__getImageDefinition(contractElement, true);\n definition.content.push(imageDefintion);\n }\n });\n\n }\n\n __addHeader(definition, json) {\n let headerNode = _.find(json.elements, {name:\"header\"});\n\n if(!_.isNil(headerNode)) {\n let imageNode = _.find(headerNode.elements, {name:\"img\"});\n let tableNode = _.find(headerNode.elements, {name:\"table\"});\n\n //The coverage report only works correctly when isWriteDataEnabled() returns true in the Unit Tests.\n definition.header = (currentPage/*, pageCount, pageSize*/) => {\n let imageDefinition = (!_.isNil(imageNode)) ? this.__getImageDefinition(imageNode, true) : null;\n let tableDefinition = (!_.isNil(tableNode)) ? this.__getTableDefinition(tableNode, {\"layout\": \"noBorders\", \"currentPage\": currentPage}) : null;\n\n if (!_.isNil(imageDefinition) && !_.isNil(tableDefinition)) {\n return [imageDefinition, tableDefinition];\n } else if (!_.isNil(tableDefinition)) {\n return tableDefinition;\n } else if (!_.isNil(imageDefinition)) {\n return imageDefinition;\n } else {\n return null;\n }\n };\n }\n }\n\n __addFooter(definition, json) {\n let footerNode = _.find(json.elements, {name:\"footer\"});\n if(!_.isNil(footerNode)) {\n let tableNode = _.find(footerNode.elements, {name:\"table\"});\n let bTableNode = !_.isNil(tableNode);\n\n //The coverage report only works correctly when isWriteDataEnabled() returns true in the Unit Tests.\n definition.footer = (currentPage/*, pageCount, pageSize*/) => {\n let tableDefinition = bTableNode ? this.__getTableDefinition(tableNode, {\"layout\": \"noBorders\", \"currentPage\":currentPage}) : null;\n return tableDefinition;\n };\n }\n }\n\n __addPrintFont(definition, printFont) {\n if (_.isObject(printFont)\n && (\"Regular\" in printFont)\n && (\"Bold\" in printFont)\n && (\"Italic\" in printFont)\n && (\"BoldItalic\" in printFont)) {\n definition.defaultStyle.font = \"PrintFont\";\n definition.printFont = printFont;\n }\n }\n\n __addDocumentMetadata(definition, documentProperties){\n definition.info = {};\n definition.info.creator = \"Consumer Goods Cloud\";\n definition.info.producer = \"Consumer Goods Cloud\";\n _.forEach(documentProperties, (value, key) => {\n definition.info[key] = value;\n });\n }\n\n __configureAutomaticPageBreak(reportLayout) {\n if(!_.isNil(reportLayout.attributes) && !_.isNil(reportLayout.attributes.automaticPageBreak)){\n this.__automaticPageBreak = reportLayout.attributes.automaticPageBreak;\n }\n }\n\n __addPageDimensionsOrientationMarginsWatermark(definition, reportLayout){\n if(!_.isNil(reportLayout.attributes) && !_.isNil(reportLayout.attributes.pageSize)){\n if (/^\\s*\\[\\s*\\d+\\s*,\\s*(\\d+|auto)\\s*\\]\\s*$/.test(reportLayout.attributes.pageSize)) {\n // pageSize is given as [width, height]\n const [width, height] = reportLayout.attributes.pageSize\n .replace(/\\s/g, '') // remove whitespace\n .replace('[', '').replace(']', '') //remove brackets\n .split(',');\n definition.pageSize = {\n width : Number(width),\n height: height === 'auto' ? height : Number(height)\n };\n this.__pdfHeight = height;\n } else {\n // assuming no other possibility for invalid pageSize format as it will be caught by during build\n definition.pageSize = reportLayout.attributes.pageSize;\n }\n }\n if(!_.isNil(reportLayout.attributes) && !_.isNil(reportLayout.attributes.watermark)){\n definition.watermark = {text: reportLayout.attributes.watermark, opacity:0.1, fontSize: 120};\n }\n if(!_.isNil(reportLayout.attributes) && !_.isNil(reportLayout.attributes.pageMargins)){\n definition.pageMargins = JSON.parse(reportLayout.attributes.pageMargins);\n }\n }\n\n __addStyles(definition, json) {\n let stylesNode = _.find(json.elements, {name:\"styles\"});\n if(_.isNil(stylesNode)) return;\n for (const styleElement of stylesNode.elements) {\n for (let [property, value] of Object.entries(styleElement.attributes)) {\n // invalid formats will be caught during build\n if (property === 'fontSize') {\n value = Number(value);\n } else if (property === 'bold' || property === 'italics') {\n value = value === 'true' || value === '1';\n } else if (property === 'margin') {\n value = JSON.parse(value);\n }\n\n if (property !== 'name') {\n definition.styles[styleElement.attributes.name][property] = value;\n }\n }\n }\n }\n\n __isLastMainRowOnPage(followingNodesOnPage) {\n let result = false;\n\n if (!_.isNil(followingNodesOnPage) && _.isArray(followingNodesOnPage)) {\n result = (followingNodesOnPage.length === 0) || !(_.some(followingNodesOnPage, y => {\n let tcid = TableCellIdentifier.fromString(y.id);\n return (tcid.isKnown() && tcid.isFirstMainRowCell());\n }));\n }\n\n return result;\n }\n\n __isFirstNodeOnNextPageFirstMainRowCell(nodesOnNextPage) {\n let result = false;\n\n if (!_.isNil(nodesOnNextPage) && _.isArray(nodesOnNextPage) && nodesOnNextPage.length > 0) {\n let firstNodeOnNextPage = _.first(nodesOnNextPage);\n let tcid = TableCellIdentifier.fromString(firstNodeOnNextPage.id);\n result = (tcid.isKnown() && tcid.isFirstMainRowCell());\n }\n\n return result;\n }\n\n __calculatePageBreakForParentChildRows(currentNode, followingNodesOnPage, nodesOnNextPage, previousNodesOnPage, tcidCurrentNode) {\n let doPageBreak = false;\n\n // dynamic pageBreak logic for parent-child rows\n if (!_.isNil(previousNodesOnPage) && _.isArray(previousNodesOnPage) && previousNodesOnPage.length > 0) {\n let previousNode = _.last(previousNodesOnPage);\n let tcidPreviousNode = TableCellIdentifier.fromString(previousNode.id);\n\n // => check if we are the first cell of a main row ...\n if (tcidCurrentNode.isFirstMainRowCell()) {\n\n if (!_.isNil(followingNodesOnPage) && _.isArray(followingNodesOnPage)) {\n\n let isCurrentNodeLastHeadOnPageX = this.__isLastMainRowOnPage(followingNodesOnPage);\n let isFirstNodeOnNextPageFirstMainRowCellX = this.__isFirstNodeOnNextPageFirstMainRowCell(nodesOnNextPage);\n let isPageBreakRelevant = (tcidPreviousNode.isKnown() && (tcidPreviousNode.isFirstMainRowCell() || tcidPreviousNode.isSubsequentMainRowCell() || tcidPreviousNode.isFirstCorrelatedRowCell() || tcidPreviousNode.isSubsequentCorrelatedRowCell()));\n\n doPageBreak = (isCurrentNodeLastHeadOnPageX && !isFirstNodeOnNextPageFirstMainRowCellX && isPageBreakRelevant);\n }\n\n } else if (tcidCurrentNode.isSubsequentMainRowCell()) {\n\n doPageBreak = (!tcidPreviousNode.isFirstMainRowCell() && !tcidPreviousNode.isSubsequentMainRowCell() || !(tcidCurrentNode.sharesMainRow(tcidPreviousNode)));\n }\n }\n\n return doPageBreak;\n }\n\n\n __calculatePageBreakForBrokenRows(currentNode, followingNodesOnPage, nodesOnNextPage, previousNodesOnPage, tcidCurrentNode) {\n let doPageBreak = false;\n\n // => check if we are the first cell of a row ...\n if (tcidCurrentNode.isFirstMainRowCell() || tcidCurrentNode.isFirstCorrelatedRowCell()) {\n // check for 'broken' row ...\n // => check if i am the last row\n let isLastRowOnPageX = (_.every(followingNodesOnPage, node => {\n let tcidNode = TableCellIdentifier.fromString(node.id);\n return !tcidNode.isKnown() || (tcidNode.isKnown() && tcidCurrentNode.sharesCorrelatedRow(tcidNode));\n }));\n\n if (isLastRowOnPageX) {\n // check if any cell of the current row extends over more than one page => pageBreak!\n // => check current cell (first cell of row)\n doPageBreak = (!_.isNil(currentNode.pageNumbers) && _.isArray(currentNode.pageNumbers) && currentNode.pageNumbers.length > 1);\n if (!doPageBreak) {\n // => check following cells on current page and cells on next page for page overlaps (other cells of row)\n doPageBreak = (_.some(followingNodesOnPage, node => {\n let tcidNode = TableCellIdentifier.fromString(node.id);\n if (tcidNode.isKnown() && tcidCurrentNode.sharesCorrelatedRow(tcidNode)) {\n return !_.isEqual(currentNode.pageNumbers, node.pageNumbers);\n }\n return false;\n }) || (_.some(nodesOnNextPage, node => {\n let tcidNode = TableCellIdentifier.fromString(node.id);\n if (tcidNode.isKnown() && tcidCurrentNode.sharesCorrelatedRow(tcidNode)) {\n return !_.isEqual(currentNode.pageNumbers, node.pageNumbers);\n }\n return false;\n })));\n }\n }\n } else if (tcidCurrentNode.isSubsequentMainRowCell() || tcidCurrentNode.isSubsequentCorrelatedRowCell()) {\n // => check other row cells ...\n if (!_.isNil(previousNodesOnPage) && _.isArray(previousNodesOnPage) && previousNodesOnPage.length > 0) {\n // check if last previous node is NOT precursor cell of current one => pageBreak!\n let previousNode = _.last(previousNodesOnPage);\n let tcidPreviousNode = TableCellIdentifier.fromString(previousNode.id);\n doPageBreak = !tcidCurrentNode.isPreviousCell(tcidPreviousNode);\n }\n }\n\n return doPageBreak;\n }\n\n __calculatePageBreakBefore(currentNode, followingNodesOnPage, nodesOnNextPage, previousNodesOnPage) {\n let doPageBreak = false;\n \n // looking for potential pageBreaks only makes sense if there are elements to be placed there (=> might require adaption for subtotals)\n if (!_.isNil(nodesOnNextPage) && _.isArray(nodesOnNextPage) && nodesOnNextPage.length > 0) {\n\n // get table cell identifier\n let tcidCurrentNode = TableCellIdentifier.fromString(currentNode.id);\n if (!_.isNil(tcidCurrentNode) && tcidCurrentNode.isKnown()) {\n\n // check for dynamic pageBreak of parent-child rows\n doPageBreak = this.__calculatePageBreakForParentChildRows(currentNode, followingNodesOnPage, nodesOnNextPage, previousNodesOnPage, tcidCurrentNode); \n if (!doPageBreak) { \n // check for dynamic pageBreak of 'broken' row\n doPageBreak = this.__calculatePageBreakForBrokenRows(currentNode, followingNodesOnPage, nodesOnNextPage, previousNodesOnPage, tcidCurrentNode); \n }\n \n if (doPageBreak && !_.isUndefined(this.__definition.dynamicPageBreak) && this.__definition.dynamicPageBreak) { \n if (tcidCurrentNode.isFirstMainRowCell() || tcidCurrentNode.isFirstCorrelatedRowCell()) {\n // cache dynamic pageBreak to turn them into manual ones during the second run ...\n this.__definition.dynamicPageBreakData.push(tcidCurrentNode.toString()); \n } else {\n doPageBreak = false;\n }\n }\n\n }\n } \n\n return doPageBreak;\n }\n\n __createPdfDocument(pdfDefinition, pdfCreationFunction) {\n // clone pdf definition if applicable ...\n let pdfDefinitionCopy = null;\n if (!_.isNil(pdfDefinition) && !_.isUndefined(pdfDefinition.dynamicPageBreak) && pdfDefinition.dynamicPageBreak &&\n !_.isNil(pdfCreationFunction) && _.isFunction(pdfCreationFunction)) {\n // init empty dynamicPageBreakData ...\n _.assign(pdfDefinition, {\n dynamicPageBreakData: []\n });\n\n pdfDefinitionCopy = _.cloneDeep(pdfDefinition);\n // skip header / footer for initial layouting and move them to final layouting\n if (!_.isUndefined(pdfDefinition.header)) {\n let headerFunction = pdfDefinition.header;\n _.assign(pdfDefinitionCopy, {\n 'header': headerFunction\n });\n _.unset(pdfDefinition, 'header');\n }\n if (!_.isUndefined(pdfDefinition.footer)) {\n let footerFunction = pdfDefinition.footer;\n _.assign(pdfDefinitionCopy, {\n 'footer': footerFunction\n });\n _.unset(pdfDefinition, 'footer');\n }\n // remove dynamic pageBreak logic\n _.unset(pdfDefinitionCopy, 'pageBreakBefore');\n }\n\n // set pdf definition to be layouted ...\n this.__definition = pdfDefinition;\n\n // exec pdfCreation function ...\n pdfCreationFunction.apply(this, [pdfDefinition]);\n\n return pdfDefinitionCopy;\n }\n\n __createFinalPdfDocument(pdfDefinition, pdfDefinitionCopy, pdfCreationFunction) {\n // perform pageBreak magic ...\n if (!_.isNil(pdfDefinition) && !_.isUndefined(pdfDefinition.dynamicPageBreak) && pdfDefinition.dynamicPageBreak &&\n !_.isUndefined(pdfDefinition.dynamicPageBreakData) && _.isArray(pdfDefinition.dynamicPageBreakData) &&\n !_.isNil(pdfDefinitionCopy) && !_.isUndefined(pdfDefinitionCopy.dynamicPageBreak) && pdfDefinitionCopy.dynamicPageBreak &&\n !_.isNil(pdfCreationFunction) && _.isFunction(pdfCreationFunction)) {\n\n // transfer dynamicPageBreakData from pdf definition to its copy\n pdfDefinitionCopy.dynamicPageBreakData = pdfDefinition.dynamicPageBreakData;\n\n this.__applyPageBreakData(pdfDefinitionCopy);\n\n // set pdf definition to be layouted ...\n this.__definition = pdfDefinitionCopy;\n\n // exec pdfCreation function ...\n pdfCreationFunction.apply(this, [pdfDefinitionCopy]);\n }\n }\n\n toPdfDefinition(json/*, format*/) {\n this.__initializePdfDefinition();\n this.__addPrintFont(this.__definition, json.printFont);\n this.__addDocumentMetadata(this.__definition, json.documentProperties);\n let reportLayout = json.reportLayout;\n this.__configureAutomaticPageBreak(reportLayout);\n this.__addPageDimensionsOrientationMarginsWatermark(this.__definition, reportLayout);\n this.__addStyles(this.__definition, reportLayout);\n this.__addHeader(this.__definition, reportLayout);\n this.__addBody(this.__definition, reportLayout);\n this.__addFooter(this.__definition,reportLayout);\n return this.__definition;\n }\n\n writeToStream(pdfDefinition, stream) {\n // setup pdf creator ...\n let printer = new PdfPrinter(ServerFonts);\n let pdfDoc = null; \n let pdfCreatorFunction = (definition) => {\n printer = new PdfPrinter(ServerFonts);\n pdfDoc = printer.createPdfKitDocument(definition, {\n tableLayouts: TableLayouts\n });\n };\n\n // create pdf and prepare for recreation if applicable ...\n let pdfDefinitionCopy = this.__createPdfDocument(pdfDefinition, pdfCreatorFunction);\n\n // recreate pdf if applicable ...\n this.__createFinalPdfDocument(pdfDefinition, pdfDefinitionCopy, pdfCreatorFunction);\n\n pdfDoc.pipe(stream);\n pdfDoc.end();\n\n return (pdfDefinitionCopy || pdfDefinition);\n }\n\n async __createPdfDocumentAsync(pdfDefinition) {\n return new Promise((resolve, reject) => {\n try {\n \n // clone pdf definition if applicable ...\n let pdfDefinitionCopy = null;\n if (!_.isNil(pdfDefinition) && !_.isUndefined(pdfDefinition.dynamicPageBreak) && pdfDefinition.dynamicPageBreak) {\n // init empty dynamicPageBreakData ...\n _.assign(pdfDefinition, {\n dynamicPageBreakData: []\n });\n\n pdfDefinitionCopy = _.cloneDeep(pdfDefinition);\n // skip header / footer for initial layouting and move them to final layouting\n if (!_.isUndefined(pdfDefinition.header)) {\n let headerFunction = pdfDefinition.header;\n _.assign(pdfDefinitionCopy, {\n 'header': headerFunction\n });\n _.unset(pdfDefinition, 'header');\n }\n if (!_.isUndefined(pdfDefinition.footer)) {\n let footerFunction = pdfDefinition.footer;\n _.assign(pdfDefinitionCopy, {\n 'footer': footerFunction\n });\n _.unset(pdfDefinition, 'footer');\n }\n // remove dynamic pageBreak logic\n _.unset(pdfDefinitionCopy, 'pageBreakBefore');\n }\n\n // set pdf definition to be layouted ...\n this.__definition = pdfDefinition; \n \n resolve(pdfDefinitionCopy);\n } catch (error) {\n reject(error);\n }\n });\n }\n\n async __createFinalPdfDocumentAsync(pdfDefinition, pdfDefinitionCopy) {\n return new Promise((resolve, reject) => {\n try {\n // perform pageBreak magic ...\n if (!_.isNil(pdfDefinition) && !_.isUndefined(pdfDefinition.dynamicPageBreak) && pdfDefinition.dynamicPageBreak &&\n !_.isUndefined(pdfDefinition.dynamicPageBreakData) && _.isArray(pdfDefinition.dynamicPageBreakData) &&\n !_.isNil(pdfDefinitionCopy) && !_.isUndefined(pdfDefinitionCopy.dynamicPageBreak) && pdfDefinitionCopy.dynamicPageBreak) {\n\n // transfer dynamicPageBreakData from pdf definition to its copy\n pdfDefinitionCopy.dynamicPageBreakData = pdfDefinition.dynamicPageBreakData;\n\n this.__applyPageBreakData(pdfDefinitionCopy);\n\n // set pdf definition to be layouted ...\n this.__definition = pdfDefinitionCopy; \n }\n resolve();\n } catch (error) {\n reject(error);\n }\n }); \n }\n\n async __getPdfDataAsync(type, pdfDefinition, previousResult = null) {\n return new Promise((resolve, reject) => {\n try {\n if (_.isNil(pdfDefinition) && !_.isNil(previousResult)) {\n resolve(previousResult);\n } else {\n let pdfDocGenerator = null;\n if (pdfDefinition.defaultStyle.font !== \"PrintFont\") {\n pdfDocGenerator = this.__pdfMake.createPdf(pdfDefinition, TableLayouts, BrowserFonts, BrowserFontsVfs.pdfMake.vfs);\n }\n else {\n pdfDocGenerator = this.__pdfMake.createPdf(pdfDefinition, TableLayouts, BrowserFonts, pdfDefinition.printFont);\n }\n \n switch (type) {\n case EXPORT_TYPE.BASE_64:\n pdfDocGenerator.getBase64((data) => {\n resolve(data);\n });\n break;\n\n case EXPORT_TYPE.BLOB:\n pdfDocGenerator.getBlob((blob) => {\n resolve(blob);\n });\n break;\n\n case EXPORT_TYPE.DATA_URL:\n pdfDocGenerator.getDataUrl((dataUrl) => {\n resolve(dataUrl);\n });\n break;\n\n default: \n throw new Error('Unknown export type: ' + type ); \n }\n }\n\n } catch (error) {\n reject(error);\n }\n });\n }\n\n async toBase64(pdfDefinition) {\n // hint: works only in browser avoid calling it in node.js\n let pdfDefinitionCopy = null;\n let firstResult = null; \n \n return this.__createPdfDocumentAsync(pdfDefinition).then((pdfDef) => {\n pdfDefinitionCopy = pdfDef;\n return this.__getPdfDataAsync(EXPORT_TYPE.BASE_64, pdfDefinition);\n }).then((pdfData) => {\n firstResult = pdfData;\n return this.__createFinalPdfDocumentAsync(pdfDefinition, pdfDefinitionCopy);\n }).then(() => {\n return this.__getPdfDataAsync(EXPORT_TYPE.BASE_64, pdfDefinitionCopy, firstResult); \n });\n \n }\n\n async toBlob(pdfDefinition) {\n // hint: works only in browser avoid calling it in node.js\n let pdfDefinitionCopy = null;\n let firstResult = null; \n \n return this.__createPdfDocumentAsync(pdfDefinition).then((pdfDef) => {\n pdfDefinitionCopy = pdfDef;\n return this.__getPdfDataAsync(EXPORT_TYPE.BLOB, pdfDefinition);\n }).then((pdfData) => {\n firstResult = pdfData;\n return this.__createFinalPdfDocumentAsync(pdfDefinition, pdfDefinitionCopy);\n }).then(() => {\n return this.__getPdfDataAsync(EXPORT_TYPE.BLOB, pdfDefinitionCopy, firstResult); \n });\n }\n \n async toDataUrl(pdfDefinition) {\n // hint: works only in browser avoid calling it in node.js\n let pdfDefinitionCopy = null;\n let firstResult = null; \n \n return this.__createPdfDocumentAsync(pdfDefinition).then((pdfDef) => {\n pdfDefinitionCopy = pdfDef;\n return this.__getPdfDataAsync(EXPORT_TYPE.DATA_URL, pdfDefinition);\n }).then((pdfData) => {\n firstResult = pdfData;\n return this.__createFinalPdfDocumentAsync(pdfDefinition, pdfDefinitionCopy);\n }).then(() => {\n return this.__getPdfDataAsync(EXPORT_TYPE.DATA_URL, pdfDefinitionCopy, firstResult); \n });\n \n }\n\n static isValidFormat(format) {\n let supportedFormats = ['A3', 'A4', 'A5', 'Legal', 'Letter', 'Tabloid'];\n return supportedFormats.includes(format);\n }\n\n}\n\n\nmodule.exports = PdfConverter;\n\n\n//# sourceURL=webpack://__FWPrinting/./src/pdfConverterClass.js?");
472
472
 
473
473
  /***/ }),
474
474
 
@@ -52,18 +52,29 @@ function __validateCommonParameters(contract, params, format){
52
52
  }
53
53
  }
54
54
 
55
- function __innerPrintLogic(printType, contract, params, _stream, format) {
55
+ function __innerPrintLogic(printType, contract, params, _stream, format, config) {
56
56
  let json = contractParser.toJson(contract, params);
57
57
  let pdfDefinition = pdfConverter.toPdfDefinition(json, format, testReportName);
58
-
59
58
  switch (printType) {
60
59
  case PRINT_TYPE.STREAM:
61
60
  pdfConverter.writeToStream(pdfDefinition, _stream);
62
61
  break;
63
62
 
64
63
  case PRINT_TYPE.BLOB:
65
- return pdfConverter.toBlob(pdfDefinition);
66
-
64
+ return new Promise((resolve, reject) => {
65
+ pdfConverter.toBlob(pdfDefinition).then((blobData)=>{
66
+ if(config && config.metaData === true){
67
+ resolve({
68
+ data: blobData,
69
+ pdfJson: json
70
+ });
71
+ } else {
72
+ resolve(blobData);
73
+ }
74
+ }, (err)=>{
75
+ reject(err);
76
+ });
77
+ });
67
78
  case PRINT_TYPE.DATA_URL:
68
79
  return pdfConverter.toDataUrl(pdfDefinition);
69
80
 
@@ -73,25 +84,25 @@ function __innerPrintLogic(printType, contract, params, _stream, format) {
73
84
  }
74
85
  }
75
86
 
76
- function printToStream(contract, params, _stream, format = "A4") {
87
+ function printToStream(contract, params, _stream, format = "A4", config = {}) {
77
88
  // Validate parameters
78
89
  if(!(_stream instanceof stream.Stream)) {
79
90
  throw new TypeError("Not a valid stream.");
80
91
  }
81
92
  __validateCommonParameters(contract, params, format);
82
- __innerPrintLogic(PRINT_TYPE.STREAM, contract, params, _stream, format);
93
+ __innerPrintLogic(PRINT_TYPE.STREAM, contract, params, _stream, format, config);
83
94
  }
84
95
 
85
- function printToDataUrl(contract, params, format = "A4") {
96
+ function printToDataUrl(contract, params, format = "A4", config = {}) {
86
97
  // Validate parameters
87
98
  __validateCommonParameters(contract, params, format);
88
- return __innerPrintLogic(PRINT_TYPE.DATA_URL, contract, params, null, format);
99
+ return __innerPrintLogic(PRINT_TYPE.DATA_URL, contract, params, null, format, config);
89
100
  }
90
101
 
91
- function printToBlob(contract, params, format = "A4") {
102
+ function printToBlob(contract, params, format = "A4", config = {}) {
92
103
  // Validate parameters
93
104
  __validateCommonParameters(contract, params, format);
94
- return __innerPrintLogic(PRINT_TYPE.BLOB, contract, params, null, format);
105
+ return __innerPrintLogic(PRINT_TYPE.BLOB, contract, params, null, format, config);
95
106
  }
96
107
 
97
108
 
@@ -102,6 +102,7 @@ class PdfConverter {
102
102
  }
103
103
 
104
104
  this.__format = new Format();
105
+ this.__pdfHeight = null;
105
106
  }
106
107
 
107
108
  __applyPageBreakData(pdfDefinition) {
@@ -212,7 +213,11 @@ class PdfConverter {
212
213
  }
213
214
 
214
215
  __getParagraphDefinition(paragraphNode, paragraphStyle) {
215
- return this.__createHeadingOrParagraphText(paragraphNode, paragraphNode.elements[0].text, paragraphStyle);
216
+ let text = '';
217
+ if (paragraphNode.elements) {
218
+ text = paragraphNode.elements[0].text;
219
+ }
220
+ return this.__createHeadingOrParagraphText(paragraphNode, text, paragraphStyle);
216
221
  }
217
222
 
218
223
  __getImageDefinition(imageNode, useAlignment) {
@@ -359,6 +364,10 @@ class PdfConverter {
359
364
  let i = 0;
360
365
 
361
366
  if (bAllowedStrings && _.isString(attribute)){
367
+ //the width can be given as a percentage only if the layout is 3-inch endless printer i.e, the height is auto
368
+ if(this.__pdfHeight === 'auto' && (/^\d+(\.\d+)?%$/).test(attribute)){
369
+ return attribute;
370
+ }
362
371
  for (i=0; i<allowedStrings.length; i++) {
363
372
  if (attribute === allowedStrings[i]) {
364
373
  return attribute;
@@ -739,7 +748,21 @@ class PdfConverter {
739
748
 
740
749
  __addPageDimensionsOrientationMarginsWatermark(definition, reportLayout){
741
750
  if(!_.isNil(reportLayout.attributes) && !_.isNil(reportLayout.attributes.pageSize)){
742
- definition.pageSize = reportLayout.attributes.pageSize;
751
+ if (/^\s*\[\s*\d+\s*,\s*(\d+|auto)\s*\]\s*$/.test(reportLayout.attributes.pageSize)) {
752
+ // pageSize is given as [width, height]
753
+ const [width, height] = reportLayout.attributes.pageSize
754
+ .replace(/\s/g, '') // remove whitespace
755
+ .replace('[', '').replace(']', '') //remove brackets
756
+ .split(',');
757
+ definition.pageSize = {
758
+ width : Number(width),
759
+ height: height === 'auto' ? height : Number(height)
760
+ };
761
+ this.__pdfHeight = height;
762
+ } else {
763
+ // assuming no other possibility for invalid pageSize format as it will be caught by during build
764
+ definition.pageSize = reportLayout.attributes.pageSize;
765
+ }
743
766
  }
744
767
  if(!_.isNil(reportLayout.attributes) && !_.isNil(reportLayout.attributes.watermark)){
745
768
  definition.watermark = {text: reportLayout.attributes.watermark, opacity:0.1, fontSize: 120};
@@ -749,6 +772,27 @@ class PdfConverter {
749
772
  }
750
773
  }
751
774
 
775
+ __addStyles(definition, json) {
776
+ let stylesNode = _.find(json.elements, {name:"styles"});
777
+ if(_.isNil(stylesNode)) return;
778
+ for (const styleElement of stylesNode.elements) {
779
+ for (let [property, value] of Object.entries(styleElement.attributes)) {
780
+ // invalid formats will be caught during build
781
+ if (property === 'fontSize') {
782
+ value = Number(value);
783
+ } else if (property === 'bold' || property === 'italics') {
784
+ value = value === 'true' || value === '1';
785
+ } else if (property === 'margin') {
786
+ value = JSON.parse(value);
787
+ }
788
+
789
+ if (property !== 'name') {
790
+ definition.styles[styleElement.attributes.name][property] = value;
791
+ }
792
+ }
793
+ }
794
+ }
795
+
752
796
  __isLastMainRowOnPage(followingNodesOnPage) {
753
797
  let result = false;
754
798
 
@@ -948,6 +992,7 @@ class PdfConverter {
948
992
  let reportLayout = json.reportLayout;
949
993
  this.__configureAutomaticPageBreak(reportLayout);
950
994
  this.__addPageDimensionsOrientationMarginsWatermark(this.__definition, reportLayout);
995
+ this.__addStyles(this.__definition, reportLayout);
951
996
  this.__addHeader(this.__definition, reportLayout);
952
997
  this.__addBody(this.__definition, reportLayout);
953
998
  this.__addFooter(this.__definition,reportLayout);