@ind-rcg/plugins-printengine 260.1004.0 → 262.1003.0-beta.4

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.
@@ -0,0 +1,58 @@
1
+ /*
2
+ * FILE_HEADER
3
+ */
4
+ 'use strict';
5
+
6
+ /**
7
+ * @module fs-shim
8
+ * Browser filesystem shim for pdfmake font loading
9
+ *
10
+ * **Source**: Custom implementation for pdfmake 0.3.x compatibility (not third-party)
11
+ *
12
+ * This module provides a minimal fs-like API that bridges pdfkit's filesystem
13
+ * dependencies with pdfmake's virtual filesystem. Required because pdfkit attempts
14
+ * to use fs.readFileSync for font loading, which is not available in browsers.
15
+ *
16
+ * The virtual filesystem is populated with font data from pdfmake's vfs_fonts.js
17
+ * on module initialization.
18
+ */
19
+
20
+ const virtualFs = require('pdfmake/js/virtual-fs.js').default;
21
+ const BrowserFontsVfs = require('pdfmake/build/vfs_fonts.js');
22
+ const LogClass = require('./logClass');
23
+ const __log = new LogClass();
24
+
25
+ // Load font data into virtual file system on module load
26
+ // BrowserFontsVfs has fonts directly as properties, not under .vfs
27
+ if (BrowserFontsVfs) {
28
+ for (let key in BrowserFontsVfs) {
29
+ if (Object.prototype.hasOwnProperty.call(BrowserFontsVfs, key)) {
30
+ try {
31
+ let data;
32
+ let encoding;
33
+ if (typeof BrowserFontsVfs[key] === 'object') {
34
+ data = BrowserFontsVfs[key].data;
35
+ encoding = BrowserFontsVfs[key].encoding || 'base64';
36
+ } else {
37
+ data = BrowserFontsVfs[key];
38
+ encoding = 'base64';
39
+ }
40
+ virtualFs.writeFileSync(key, data, encoding);
41
+ } catch (e) {
42
+ __log.error('Failed to load font into virtual filesystem:', key, e);
43
+ }
44
+ }
45
+ }
46
+ }
47
+
48
+ module.exports = {
49
+ readFileSync: function(filename, options) {
50
+ return virtualFs.readFileSync(filename, options);
51
+ },
52
+ existsSync: function(filename) {
53
+ return virtualFs.existsSync(filename);
54
+ },
55
+ writeFileSync: function(filename, content, options) {
56
+ return virtualFs.writeFileSync(filename, content, options);
57
+ }
58
+ };
@@ -4,12 +4,13 @@
4
4
  'use strict';
5
5
 
6
6
  const _ = require('lodash');
7
- const PdfPrinter = require('pdfmake');
7
+ const PdfPrinter = require('pdfmake/js/Printer').default;
8
8
  const Format = require('./formatClass');
9
9
  const TableCellIdentifier = require('./tableCellIdentifier');
10
10
 
11
11
  // required for webpack include (browser impl), used in conjunction with BrowserFonts definition
12
- const BrowserFontsVfs = require('pdfmake/build/vfs_fonts.js');
12
+ // BrowserFontsVfs now loaded by fs-shim.js to avoid circular dependency and integrate with virtual filesystem
13
+ // const BrowserFontsVfs = require('pdfmake/build/vfs_fonts.js');
13
14
  const classLog = require("./logClass");
14
15
 
15
16
  // => use 'Roboto' font (pdfMake default) due to licensing (Apache 2.0)
@@ -38,6 +39,12 @@ const BrowserFonts = {
38
39
  }
39
40
  };
40
41
 
42
+ // pdfmake browser components for PDF generation
43
+ const PdfMakeBase = require('pdfmake/js/base.js').default;
44
+ const OutputDocumentBrowser = require('pdfmake/js/browser-extensions/OutputDocumentBrowser.js').default;
45
+ const URLResolver = require('pdfmake/js/URLResolver.js').default;
46
+ const virtualFs = require('pdfmake/js/virtual-fs.js').default;
47
+
41
48
  const TableLayouts = {
42
49
  lightHorizontalLinesMainItemsOnly: {
43
50
  hLineWidth: function (i, node) {
@@ -100,10 +107,33 @@ Object.freeze(EXPORT_TYPE);
100
107
  class PdfConverter {
101
108
  constructor() {
102
109
  this.__pdfMake = null;
103
- if(typeof pdfMake !== "undefined")
110
+
111
+ // First try to use global pdfMake (for tests or when pdfmake is loaded separately)
112
+ if(typeof global !== "undefined" && global.pdfMake)
113
+ {
114
+ this.__pdfMake = global.pdfMake;
115
+ }
116
+ else if(typeof pdfMake !== "undefined")
104
117
  {
105
118
  this.__pdfMake = pdfMake;
106
119
  }
120
+ // Fall back to creating browser pdfmake instance (for webpack bundled builds)
121
+ else if (PdfMakeBase && OutputDocumentBrowser && URLResolver) {
122
+ // Create browser-specific pdfmake instance
123
+ class BrowserPdfMake extends PdfMakeBase {
124
+ constructor() {
125
+ super();
126
+ this.urlResolver = () => new URLResolver(this.virtualfs);
127
+ this.fonts = BrowserFonts;
128
+ this.tableLayouts = TableLayouts;
129
+ // Note: Font data is loaded into virtualfs by fs-shim.js
130
+ }
131
+ _transformToDocument(doc) {
132
+ return new OutputDocumentBrowser(doc);
133
+ }
134
+ }
135
+ this.__pdfMake = new BrowserPdfMake();
136
+ }
107
137
 
108
138
  this.__format = new Format();
109
139
  this.__pdfHeight = null;
@@ -1006,8 +1036,15 @@ class PdfConverter {
1006
1036
  return doPageBreak;
1007
1037
  }
1008
1038
 
1009
- __calculatePageBreakBefore(currentNode, followingNodesOnPage, nodesOnNextPage, previousNodesOnPage) {
1039
+ __calculatePageBreakBefore(currentNode, nodeGetters) {
1010
1040
  let doPageBreak = false;
1041
+
1042
+ // pdfmake 0.3.x API: nodeGetters contains getter functions - validate availability
1043
+ if (!nodeGetters || typeof nodeGetters.getNodesOnNextPage !== 'function') {
1044
+ return false;
1045
+ }
1046
+
1047
+ const nodesOnNextPage = nodeGetters.getNodesOnNextPage();
1011
1048
 
1012
1049
  // looking for potential pageBreaks only makes sense if there are elements to be placed there (=> might require adaption for subtotals)
1013
1050
  if (!_.isNil(nodesOnNextPage) && _.isArray(nodesOnNextPage) && nodesOnNextPage.length > 0) {
@@ -1016,6 +1053,10 @@ class PdfConverter {
1016
1053
  let tcidCurrentNode = TableCellIdentifier.fromString(currentNode.id);
1017
1054
  if (!_.isNil(tcidCurrentNode) && tcidCurrentNode.isKnown()) {
1018
1055
 
1056
+ // pdfmake 0.3.x: get the node arrays via getter functions
1057
+ const followingNodesOnPage = nodeGetters.getFollowingNodesOnPage();
1058
+ const previousNodesOnPage = nodeGetters.getPreviousNodesOnPage();
1059
+
1019
1060
  // check for dynamic pageBreak of parent-child rows
1020
1061
  doPageBreak = this.__calculatePageBreakForParentChildRows(currentNode, followingNodesOnPage, nodesOnNextPage, previousNodesOnPage, tcidCurrentNode);
1021
1062
  if (!doPageBreak) {
@@ -1038,7 +1079,7 @@ class PdfConverter {
1038
1079
  return doPageBreak;
1039
1080
  }
1040
1081
 
1041
- __createPdfDocument(pdfDefinition, pdfCreationFunction) {
1082
+ async __createPdfDocument(pdfDefinition, pdfCreationFunction) {
1042
1083
  // clone pdf definition if applicable ...
1043
1084
  let pdfDefinitionCopy = null;
1044
1085
  if (!_.isNil(pdfDefinition) && !_.isUndefined(pdfDefinition.dynamicPageBreak) && pdfDefinition.dynamicPageBreak &&
@@ -1072,12 +1113,12 @@ class PdfConverter {
1072
1113
  this.__definition = pdfDefinition;
1073
1114
 
1074
1115
  // exec pdfCreation function ...
1075
- pdfCreationFunction.apply(this, [pdfDefinition]);
1116
+ await pdfCreationFunction.apply(this, [pdfDefinition]);
1076
1117
 
1077
1118
  return pdfDefinitionCopy;
1078
1119
  }
1079
1120
 
1080
- __createFinalPdfDocument(pdfDefinition, pdfDefinitionCopy, pdfCreationFunction) {
1121
+ async __createFinalPdfDocument(pdfDefinition, pdfDefinitionCopy, pdfCreationFunction) {
1081
1122
  // perform pageBreak magic ...
1082
1123
  if (!_.isNil(pdfDefinition) && !_.isUndefined(pdfDefinition.dynamicPageBreak) && pdfDefinition.dynamicPageBreak &&
1083
1124
  !_.isUndefined(pdfDefinition.dynamicPageBreakData) && _.isArray(pdfDefinition.dynamicPageBreakData) &&
@@ -1093,7 +1134,7 @@ class PdfConverter {
1093
1134
  this.__definition = pdfDefinitionCopy;
1094
1135
 
1095
1136
  // exec pdfCreation function ...
1096
- pdfCreationFunction.apply(this, [pdfDefinitionCopy]);
1137
+ await pdfCreationFunction.apply(this, [pdfDefinitionCopy]);
1097
1138
  }
1098
1139
  }
1099
1140
 
@@ -1111,22 +1152,22 @@ class PdfConverter {
1111
1152
  return this.__definition;
1112
1153
  }
1113
1154
 
1114
- writeToStream(pdfDefinition, stream) {
1155
+ async writeToStream(pdfDefinition, stream) {
1115
1156
  // setup pdf creator ...
1116
1157
  let printer = new PdfPrinter(ServerFonts);
1117
1158
  let pdfDoc = null;
1118
- let pdfCreatorFunction = (definition) => {
1159
+ let pdfCreatorFunction = async (definition) => {
1119
1160
  printer = new PdfPrinter(ServerFonts);
1120
- pdfDoc = printer.createPdfKitDocument(definition, {
1161
+ pdfDoc = await printer.createPdfKitDocument(definition, {
1121
1162
  tableLayouts: TableLayouts
1122
1163
  });
1123
1164
  };
1124
1165
 
1125
1166
  // create pdf and prepare for recreation if applicable ...
1126
- let pdfDefinitionCopy = this.__createPdfDocument(pdfDefinition, pdfCreatorFunction);
1167
+ let pdfDefinitionCopy = await this.__createPdfDocument(pdfDefinition, pdfCreatorFunction);
1127
1168
 
1128
1169
  // recreate pdf if applicable ...
1129
- this.__createFinalPdfDocument(pdfDefinition, pdfDefinitionCopy, pdfCreatorFunction);
1170
+ await this.__createFinalPdfDocument(pdfDefinition, pdfDefinitionCopy, pdfCreatorFunction);
1130
1171
 
1131
1172
  pdfDoc.pipe(stream);
1132
1173
  pdfDoc.end();
@@ -1199,48 +1240,66 @@ class PdfConverter {
1199
1240
  });
1200
1241
  }
1201
1242
 
1202
- async __getPdfDataAsync(type, pdfDefinition, previousResult = null) {
1203
- return new Promise((resolve, reject) => {
1204
- try {
1205
- if (_.isNil(pdfDefinition) && !_.isNil(previousResult)) {
1206
- resolve(previousResult);
1207
- } else {
1208
- let pdfDocGenerator = null;
1209
- if (pdfDefinition.defaultStyle.font !== "PrintFont") {
1210
- pdfDocGenerator = this.__pdfMake.createPdf(pdfDefinition, TableLayouts, BrowserFonts, BrowserFontsVfs.vfs);
1211
- }
1212
- else {
1213
- pdfDocGenerator = this.__pdfMake.createPdf(pdfDefinition, TableLayouts, BrowserFonts, pdfDefinition.printFont);
1214
- }
1215
-
1216
- switch (type) {
1217
- case EXPORT_TYPE.BASE_64:
1218
- pdfDocGenerator.getBase64((data) => {
1219
- resolve(data);
1220
- });
1221
- break;
1222
-
1223
- case EXPORT_TYPE.BLOB:
1224
- pdfDocGenerator.getBlob((blob) => {
1225
- resolve(blob);
1226
- });
1227
- break;
1228
-
1229
- case EXPORT_TYPE.DATA_URL:
1230
- pdfDocGenerator.getDataUrl((dataUrl) => {
1231
- resolve(dataUrl);
1232
- });
1233
- break;
1234
-
1235
- default:
1236
- throw new Error('Unknown export type: ' + type );
1237
- }
1243
+ /**
1244
+ * Load custom printFont data into pdfmake's virtual file system.
1245
+ * Required for pdfmake 0.3.x where fonts must be in VFS before use.
1246
+ *
1247
+ * @param {Object} printFont - Object with Regular, Bold, Italic, BoldItalic keys containing base64 font data
1248
+ */
1249
+ __loadCustomFontsToVfs(printFont) {
1250
+ if (!_.isObject(printFont)) {
1251
+ return;
1252
+ }
1253
+
1254
+ const fontKeys = ['Regular', 'Bold', 'Italic', 'BoldItalic'];
1255
+ for (const key of fontKeys) {
1256
+ if (key in printFont && printFont[key]) {
1257
+ try {
1258
+ // Font data is already base64 encoded
1259
+ virtualFs.writeFileSync(key, printFont[key], 'base64');
1260
+ } catch (e) {
1261
+ __log.error('Failed to load custom font into virtual filesystem:', key, e);
1238
1262
  }
1263
+ }
1264
+ }
1265
+ }
1239
1266
 
1240
- } catch (error) {
1241
- reject(error);
1267
+ async __getPdfDataAsync(type, pdfDefinition, previousResult = null) {
1268
+ if (_.isNil(pdfDefinition) && !_.isNil(previousResult)) {
1269
+ return previousResult;
1270
+ }
1271
+
1272
+ try {
1273
+ // Load custom fonts into VFS if present (required for pdfmake 0.3.x)
1274
+ if (pdfDefinition.printFont) {
1275
+ this.__loadCustomFontsToVfs(pdfDefinition.printFont);
1242
1276
  }
1243
- });
1277
+
1278
+ // pdfmake 0.3.x API: createPdf(docDefinition, options)
1279
+ // fonts and tableLayouts are set on the pdfmake instance - validate initialization
1280
+ if (!this.__pdfMake || typeof this.__pdfMake.createPdf !== 'function') {
1281
+ throw new Error('pdfMake instance not properly initialized');
1282
+ }
1283
+
1284
+ let pdfDocGenerator = this.__pdfMake.createPdf(pdfDefinition, {});
1285
+
1286
+ // pdfmake 0.3.x returns Promises, not callbacks
1287
+ switch (type) {
1288
+ case EXPORT_TYPE.BASE_64: {
1289
+ return await pdfDocGenerator.getBase64();
1290
+ }
1291
+ case EXPORT_TYPE.BLOB: {
1292
+ return await pdfDocGenerator.getBlob();
1293
+ }
1294
+ case EXPORT_TYPE.DATA_URL: {
1295
+ return await pdfDocGenerator.getDataUrl();
1296
+ }
1297
+ default:
1298
+ throw new Error('Unknown export type: ' + type);
1299
+ }
1300
+ } catch (error) {
1301
+ throw new Error(`PDF ${type} export failed: ${error.message}`);
1302
+ }
1244
1303
  }
1245
1304
 
1246
1305
  async toBase64(pdfDefinition) {