@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.
package/dist/dev/printEngine.js
CHANGED
|
@@ -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
|
|
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
|
|
package/dist/dev/src/index.js
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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
|
-
|
|
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);
|