pdfmake 0.3.0-beta.7 → 0.3.0-beta.9

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.
@@ -3,5 +3,5 @@
3
3
  exports.__esModule = true;
4
4
  exports.default = void 0;
5
5
  var _source = _interopRequireDefault(require("./svg-to-pdfkit/source.js"));
6
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
6
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
7
7
  var _default = exports.default = _source.default;
package/js/DocMeasure.js CHANGED
@@ -10,7 +10,7 @@ var _variableType = require("./helpers/variableType");
10
10
  var _node = require("./helpers/node");
11
11
  var _tools = require("./helpers/tools");
12
12
  var _qrEnc = _interopRequireDefault(require("./qrEnc.js"));
13
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
13
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
14
14
  class DocMeasure {
15
15
  constructor(pdfDocument, styleDictionary, defaultStyle, svgMeasure, tableLayouts) {
16
16
  this.pdfDocument = pdfDocument;
@@ -396,15 +396,14 @@ class DocMeasure {
396
396
  if (item.listMarker._inlines) {
397
397
  node._gapSize.width = Math.max(node._gapSize.width, item.listMarker._inlines[0].width);
398
398
  }
399
- } // TODO: else - nested lists numbering
400
-
399
+ if (node.reversed) {
400
+ counter--;
401
+ } else {
402
+ counter++;
403
+ }
404
+ }
401
405
  node._minWidth = Math.max(node._minWidth, items[i]._minWidth);
402
406
  node._maxWidth = Math.max(node._maxWidth, items[i]._maxWidth);
403
- if (node.reversed) {
404
- counter--;
405
- } else {
406
- counter++;
407
- }
408
407
  }
409
408
  node._minWidth += node._gapSize.width;
410
409
  node._maxWidth += node._gapSize.width;
@@ -18,7 +18,6 @@ class DocumentContext extends _events.EventEmitter {
18
18
  this.availableHeight = 0;
19
19
  this.page = -1;
20
20
  this.snapshots = [];
21
- this.endingCell = null;
22
21
  this.backgroundLength = [];
23
22
  this.addPage(pageSize);
24
23
  }
@@ -36,15 +35,13 @@ class DocumentContext extends _events.EventEmitter {
36
35
  availableWidth: this.availableWidth,
37
36
  page: this.page
38
37
  },
39
- endingCell: this.endingCell,
40
38
  lastColumnWidth: this.lastColumnWidth
41
39
  });
42
40
  this.lastColumnWidth = 0;
43
41
  }
44
42
  beginColumn(width, offset, endingCell) {
45
43
  let saved = this.snapshots[this.snapshots.length - 1];
46
- this.calculateBottomMost(saved);
47
- this.endingCell = endingCell;
44
+ this.calculateBottomMost(saved, endingCell);
48
45
  this.page = saved.page;
49
46
  this.x = this.x + this.lastColumnWidth + (offset || 0);
50
47
  this.y = saved.y;
@@ -52,10 +49,9 @@ class DocumentContext extends _events.EventEmitter {
52
49
  this.availableHeight = saved.availableHeight;
53
50
  this.lastColumnWidth = width;
54
51
  }
55
- calculateBottomMost(destContext) {
56
- if (this.endingCell) {
57
- this.saveContextInEndingCell(this.endingCell);
58
- this.endingCell = null;
52
+ calculateBottomMost(destContext, endingCell) {
53
+ if (endingCell) {
54
+ this.saveContextInEndingCell(endingCell);
59
55
  } else {
60
56
  destContext.bottomMost = bottomMostContext(this, destContext.bottomMost);
61
57
  }
@@ -78,10 +74,9 @@ class DocumentContext extends _events.EventEmitter {
78
74
  lastColumnWidth: this.lastColumnWidth
79
75
  };
80
76
  }
81
- completeColumnGroup(height) {
77
+ completeColumnGroup(height, endingCell) {
82
78
  let saved = this.snapshots.pop();
83
- this.calculateBottomMost(saved);
84
- this.endingCell = null;
79
+ this.calculateBottomMost(saved, endingCell);
85
80
  this.x = saved.x;
86
81
  let y = saved.bottomMost.y;
87
82
  if (height) {
@@ -148,7 +143,6 @@ class DocumentContext extends _events.EventEmitter {
148
143
  availableHeight: this.availableHeight,
149
144
  availableWidth: this.availableWidth,
150
145
  page: this.page,
151
- endingCell: this.endingCell,
152
146
  lastColumnWidth: this.lastColumnWidth
153
147
  });
154
148
  }
@@ -159,7 +153,6 @@ class DocumentContext extends _events.EventEmitter {
159
153
  this.availableWidth = saved.availableWidth;
160
154
  this.availableHeight = saved.availableHeight;
161
155
  this.page = saved.page;
162
- this.endingCell = saved.endingCell;
163
156
  this.lastColumnWidth = saved.lastColumnWidth;
164
157
  }
165
158
  moveToNextPage(pageOrientation) {
@@ -6,7 +6,7 @@ var _variableType = require("./helpers/variableType");
6
6
  var _tools = require("./helpers/tools");
7
7
  var _DocumentContext = _interopRequireDefault(require("./DocumentContext"));
8
8
  var _events = require("events");
9
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
9
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
10
10
  /**
11
11
  * A line/vector writer, which adds elements to current page and sets
12
12
  * their positions based on the context
@@ -14,7 +14,7 @@ var _node = require("./helpers/node");
14
14
  var _tools = require("./helpers/tools");
15
15
  var _TextInlines = _interopRequireDefault(require("./TextInlines"));
16
16
  var _StyleContextStack = _interopRequireDefault(require("./StyleContextStack"));
17
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
17
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
18
18
  function addAll(target, otherArray) {
19
19
  otherArray.forEach(item => {
20
20
  target.push(item);
@@ -425,6 +425,20 @@ class LayoutBuilder {
425
425
  return gaps;
426
426
  }
427
427
  }
428
+ findStartingSpanCell(arr, i) {
429
+ let requiredColspan = 1;
430
+ for (let index = i - 1; index >= 0; index--) {
431
+ if (!arr[index]._span) {
432
+ if (arr[index].rowSpan > 1 && (arr[index].colSpan || 1) === requiredColspan) {
433
+ return arr[index];
434
+ } else {
435
+ return null;
436
+ }
437
+ }
438
+ requiredColspan++;
439
+ }
440
+ return null;
441
+ }
428
442
  processRow(columns, widths, gaps, tableBody, tableRow, height) {
429
443
  const storePageBreakData = data => {
430
444
  let pageDesc;
@@ -456,16 +470,52 @@ class LayoutBuilder {
456
470
  width += widths[++i]._calcWidth + gaps[i];
457
471
  }
458
472
  }
459
- this.writer.context().beginColumn(width, leftOffset, getEndingCell(column, i));
473
+
474
+ // if rowspan starts in this cell, we retrieve the last cell affected by the rowspan
475
+ const endingCell = getEndingCell(column, i);
476
+ if (endingCell) {
477
+ // We store a reference of the ending cell in the first cell of the rowspan
478
+ column._endingCell = endingCell;
479
+ }
480
+
481
+ // Check if exists and retrieve the cell that started the rowspan in case we are in the cell just after
482
+ let startingSpanCell = this.findStartingSpanCell(columns, i);
483
+ let endingSpanCell = null;
484
+ if (startingSpanCell && startingSpanCell._endingCell) {
485
+ // Reference to the last cell of the rowspan
486
+ endingSpanCell = startingSpanCell._endingCell;
487
+ }
488
+
489
+ // We pass the endingSpanCell reference to store the context just after processing rowspan cell
490
+ this.writer.context().beginColumn(width, leftOffset, endingSpanCell);
460
491
  if (!column._span) {
461
492
  this.processNode(column);
462
493
  addAll(positions, column.positions);
463
494
  } else if (column._columnEndingContext) {
464
495
  // row-span ending
496
+ // Recover the context after processing the rowspanned cell
465
497
  this.writer.context().markEnding(column);
466
498
  }
467
499
  }
468
- this.writer.context().completeColumnGroup(height);
500
+
501
+ // Check if last cell is part of a span
502
+ let endingSpanCell = null;
503
+ const lastColumn = columns.length > 0 ? columns[columns.length - 1] : null;
504
+ if (lastColumn) {
505
+ // Previous column cell has a rowspan
506
+ if (lastColumn._endingCell) {
507
+ endingSpanCell = lastColumn._endingCell;
508
+ // Previous column cell is part of a span
509
+ } else if (lastColumn._span === true) {
510
+ // We get the cell that started the span where we set a reference to the ending cell
511
+ const startingSpanCell = this.findStartingSpanCell(columns, columns.length);
512
+ if (startingSpanCell) {
513
+ // Context will be stored here (ending cell)
514
+ endingSpanCell = startingSpanCell._endingCell;
515
+ }
516
+ }
517
+ }
518
+ this.writer.context().completeColumnGroup(height, endingSpanCell);
469
519
  this.writer.removeListener('pageChanged', storePageBreakData);
470
520
  return {
471
521
  pageBreaks: pageBreaks,
@@ -4,7 +4,7 @@ exports.__esModule = true;
4
4
  exports.default = void 0;
5
5
  var _OutputDocument = _interopRequireDefault(require("./OutputDocument"));
6
6
  var _fs = _interopRequireDefault(require("fs"));
7
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
7
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
8
8
  class OutputDocumentServer extends _OutputDocument.default {
9
9
  /**
10
10
  * @param {string} filename
package/js/PDFDocument.js CHANGED
@@ -3,7 +3,7 @@
3
3
  exports.__esModule = true;
4
4
  exports.default = void 0;
5
5
  var _pdfkit = _interopRequireDefault(require("@foliojs-fork/pdfkit"));
6
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
6
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
7
7
  const typeName = (bold, italics) => {
8
8
  let type = 'normal';
9
9
  if (bold && italics) {
@@ -3,7 +3,7 @@
3
3
  exports.__esModule = true;
4
4
  exports.default = void 0;
5
5
  var _ElementWriter = _interopRequireDefault(require("./ElementWriter"));
6
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
6
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
7
7
  /**
8
8
  * An extended ElementWriter which can handle:
9
9
  * - page-breaks (it adds new pages when there's not enough space left),
package/js/PageSize.js CHANGED
@@ -5,7 +5,7 @@ exports.normalizePageMargin = normalizePageMargin;
5
5
  exports.normalizePageSize = normalizePageSize;
6
6
  var _standardPageSizes = _interopRequireDefault(require("./standardPageSizes"));
7
7
  var _variableType = require("./helpers/variableType");
8
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
8
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
9
9
  function normalizePageSize(pageSize, pageOrientation) {
10
10
  function isNeedSwapPageSizes(pageOrientation) {
11
11
  if ((0, _variableType.isString)(pageOrientation)) {
package/js/Printer.js CHANGED
@@ -9,7 +9,7 @@ var _PageSize = require("./PageSize");
9
9
  var _tableLayouts = require("./tableLayouts");
10
10
  var _Renderer = _interopRequireDefault(require("./Renderer"));
11
11
  var _variableType = require("./helpers/variableType");
12
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
12
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
13
13
  /**
14
14
  * Printer which turns document definition into a pdf
15
15
  *
package/js/Renderer.js CHANGED
@@ -6,7 +6,7 @@ var _TextDecorator = _interopRequireDefault(require("./TextDecorator"));
6
6
  var _TextInlines = _interopRequireDefault(require("./TextInlines"));
7
7
  var _variableType = require("./helpers/variableType");
8
8
  var _svgToPdfkit = _interopRequireDefault(require("./3rd-party/svg-to-pdfkit"));
9
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
9
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
10
10
  const findFont = (fonts, requiredFonts, defaultFont) => {
11
11
  for (let i = 0; i < requiredFonts.length; i++) {
12
12
  let requiredFont = requiredFonts[i].toLowerCase();
package/js/SVGMeasure.js CHANGED
@@ -3,7 +3,7 @@
3
3
  exports.__esModule = true;
4
4
  exports.default = void 0;
5
5
  var _xmldoc = _interopRequireDefault(require("xmldoc"));
6
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
6
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
7
7
  /**
8
8
  * Strip unit postfix, parse number, but return undefined instead of NaN for bad input
9
9
  *
@@ -75,26 +75,10 @@ class StyleContextStack {
75
75
  for (let i = 0, l = styleNames.length; i < l; i++) {
76
76
  this.push(styleNames[i]);
77
77
  }
78
- let styleProperties = ['font', 'fontSize', 'fontFeatures', 'bold', 'italics', 'alignment', 'color', 'columnGap', 'fillColor', 'fillOpacity', 'decoration', 'decorationStyle', 'decorationColor', 'background', 'lineHeight', 'characterSpacing', 'noWrap', 'markerColor', 'leadingIndent', 'sup', 'sub'
79
- //'tableCellPadding'
80
- // 'cellBorder',
81
- // 'headerCellBorder',
82
- // 'oddRowCellBorder',
83
- // 'evenRowCellBorder',
84
- // 'tableBorder'
85
- ];
86
- let styleOverrideObject = {};
87
- let pushStyleOverrideObject = false;
88
- styleProperties.forEach(key => {
89
- if ((0, _variableType.isValue)(item[key])) {
90
- styleOverrideObject[key] = item[key];
91
- pushStyleOverrideObject = true;
92
- }
93
- });
94
- if (pushStyleOverrideObject) {
95
- this.push(styleOverrideObject);
96
- }
97
- return styleNames.length + (pushStyleOverrideObject ? 1 : 0);
78
+
79
+ // rather than spend significant time making a styleOverrideObject, just add item
80
+ this.push(item);
81
+ return styleNames.length + 1;
98
82
  }
99
83
 
100
84
  /**
@@ -4,7 +4,7 @@ exports.__esModule = true;
4
4
  exports.default = void 0;
5
5
  var _columnCalculator = _interopRequireDefault(require("./columnCalculator"));
6
6
  var _variableType = require("./helpers/variableType");
7
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
7
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
8
8
  class TableProcessor {
9
9
  constructor(tableNode) {
10
10
  this.tableNode = tableNode;
@@ -92,15 +92,26 @@ class TableProcessor {
92
92
  this.offsets = tableNode._offsets;
93
93
  this.layout = tableNode._layout;
94
94
  availableWidth = writer.context().availableWidth - this.offsets.total;
95
- _columnCalculator.default.buildColumnWidths(tableNode.table.widths, availableWidth);
95
+ _columnCalculator.default.buildColumnWidths(tableNode.table.widths, availableWidth, this.offsets.total, tableNode);
96
96
  this.tableWidth = tableNode._offsets.total + getTableInnerContentWidth();
97
97
  this.rowSpanData = prepareRowSpanData();
98
98
  this.cleanUpRepeatables = false;
99
- this.headerRows = tableNode.table.headerRows || 0;
100
- if (this.headerRows > tableNode.table.body.length) {
101
- throw new Error(`Too few rows in the table. Property headerRows requires at least ${this.headerRows}, contains only ${tableNode.table.body.length}`);
99
+
100
+ // headersRows and rowsWithoutPageBreak (headerRows + keepWithHeaderRows)
101
+ this.headerRows = 0;
102
+ this.rowsWithoutPageBreak = 0;
103
+ const headerRows = tableNode.table.headerRows;
104
+ if ((0, _variableType.isPositiveInteger)(headerRows)) {
105
+ this.headerRows = headerRows;
106
+ if (this.headerRows > tableNode.table.body.length) {
107
+ throw new Error(`Too few rows in the table. Property headerRows requires at least ${this.headerRows}, contains only ${tableNode.table.body.length}`);
108
+ }
109
+ this.rowsWithoutPageBreak = this.headerRows;
110
+ const keepWithHeaderRows = tableNode.table.keepWithHeaderRows;
111
+ if ((0, _variableType.isPositiveInteger)(keepWithHeaderRows)) {
112
+ this.rowsWithoutPageBreak += keepWithHeaderRows;
113
+ }
102
114
  }
103
- this.rowsWithoutPageBreak = this.headerRows + (tableNode.table.keepWithHeaderRows || 0);
104
115
  this.dontBreakRows = tableNode.table.dontBreakRows || false;
105
116
  if (this.rowsWithoutPageBreak) {
106
117
  writer.beginUnbreakableBlock();
package/js/TextBreaker.js CHANGED
@@ -5,7 +5,7 @@ exports.default = void 0;
5
5
  var _linebreak = _interopRequireDefault(require("@foliojs-fork/linebreak"));
6
6
  var _variableType = require("./helpers/variableType");
7
7
  var _StyleContextStack = _interopRequireDefault(require("./StyleContextStack"));
8
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
8
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
9
9
  /**
10
10
  * @param {string} text
11
11
  * @param {boolean} noWrap
package/js/TextInlines.js CHANGED
@@ -4,7 +4,7 @@ exports.__esModule = true;
4
4
  exports.default = void 0;
5
5
  var _TextBreaker = _interopRequireDefault(require("./TextBreaker"));
6
6
  var _StyleContextStack = _interopRequireDefault(require("./StyleContextStack"));
7
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
7
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
8
8
  const LEADING = /^(\s)+/g;
9
9
  const TRAILING = /(\s)+$/g;
10
10
 
package/js/URLResolver.js CHANGED
@@ -4,7 +4,7 @@ exports.__esModule = true;
4
4
  exports.default = void 0;
5
5
  var _http = _interopRequireDefault(require("http"));
6
6
  var _https = _interopRequireDefault(require("https"));
7
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
7
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
8
8
  const fetchUrl = (url, headers = {}) => {
9
9
  return new Promise((resolve, reject) => {
10
10
  const parsedUrl = new URL(url);
package/js/base.js CHANGED
@@ -5,7 +5,7 @@ exports.default = void 0;
5
5
  var _Printer = _interopRequireDefault(require("./Printer"));
6
6
  var _virtualFs = _interopRequireDefault(require("./virtual-fs"));
7
7
  var _tools = require("./helpers/tools");
8
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
8
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
9
9
  class pdfmake {
10
10
  constructor() {
11
11
  this.virtualfs = _virtualFs.default;
@@ -4,7 +4,7 @@ exports.__esModule = true;
4
4
  exports.default = void 0;
5
5
  var _OutputDocument = _interopRequireDefault(require("../OutputDocument"));
6
6
  var _fileSaver = require("file-saver");
7
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
7
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
8
8
  /**
9
9
  * @returns {Window}
10
10
  */
@@ -7,7 +7,7 @@ var _OutputDocumentBrowser = _interopRequireDefault(require("./OutputDocumentBro
7
7
  var _URLBrowserResolver = _interopRequireDefault(require("./URLBrowserResolver"));
8
8
  var _fs = _interopRequireDefault(require("fs"));
9
9
  var _configurator = _interopRequireDefault(require("core-js/configurator"));
10
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
10
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
11
11
  // core-js: Polyfills will be used only if natives completely unavailable.
12
12
  (0, _configurator.default)({
13
13
  useNative: ['Promise']
@@ -3,7 +3,7 @@
3
3
  exports.__esModule = true;
4
4
  exports.default = void 0;
5
5
  var _variableType = require("./helpers/variableType");
6
- function buildColumnWidths(columns, availableWidth) {
6
+ function buildColumnWidths(columns, availableWidth, offsetTotal = 0, tableNode) {
7
7
  let autoColumns = [];
8
8
  let autoMin = 0;
9
9
  let autoMax = 0;
@@ -25,10 +25,29 @@ function buildColumnWidths(columns, availableWidth) {
25
25
  fixedColumns.push(column);
26
26
  }
27
27
  });
28
- fixedColumns.forEach(col => {
28
+ fixedColumns.forEach((col, colIndex) => {
29
29
  // width specified as %
30
30
  if ((0, _variableType.isString)(col.width) && /\d+%/.test(col.width)) {
31
- col.width = parseFloat(col.width) * initial_availableWidth / 100;
31
+ // In tables we have to take into consideration the reserved width for paddings and borders
32
+ let reservedWidth = 0;
33
+ if (tableNode) {
34
+ const paddingLeft = tableNode._layout.paddingLeft(colIndex, tableNode);
35
+ const paddingRight = tableNode._layout.paddingRight(colIndex, tableNode);
36
+ const borderLeft = tableNode._layout.vLineWidth(colIndex, tableNode);
37
+ const borderRight = tableNode._layout.vLineWidth(colIndex + 1, tableNode);
38
+ if (colIndex === 0) {
39
+ // first column assumes whole borderLeft and half of border right
40
+ reservedWidth = paddingLeft + paddingRight + borderLeft + borderRight / 2;
41
+ } else if (colIndex === fixedColumns.length - 1) {
42
+ // last column assumes whole borderRight and half of border left
43
+ reservedWidth = paddingLeft + paddingRight + borderLeft / 2 + borderRight;
44
+ } else {
45
+ // Columns in the middle assume half of each border
46
+ reservedWidth = paddingLeft + paddingRight + borderLeft / 2 + borderRight / 2;
47
+ }
48
+ }
49
+ const totalAvailableWidth = initial_availableWidth + offsetTotal;
50
+ col.width = parseFloat(col.width) * totalAvailableWidth / 100 - reservedWidth;
32
51
  }
33
52
  if (col.width < col._minWidth && col.elasticWidth) {
34
53
  col._calcWidth = col._minWidth;
@@ -4,6 +4,7 @@ exports.__esModule = true;
4
4
  exports.isEmptyObject = isEmptyObject;
5
5
  exports.isNumber = isNumber;
6
6
  exports.isObject = isObject;
7
+ exports.isPositiveInteger = isPositiveInteger;
7
8
  exports.isString = isString;
8
9
  exports.isValue = isValue;
9
10
  /**
@@ -22,6 +23,17 @@ function isNumber(variable) {
22
23
  return typeof variable === 'number' || variable instanceof Number;
23
24
  }
24
25
 
26
+ /**
27
+ * @param {any} variable
28
+ * @returns {boolean}
29
+ */
30
+ function isPositiveInteger(variable) {
31
+ if (!isNumber(variable) || !Number.isInteger(variable) || variable <= 0) {
32
+ return false;
33
+ }
34
+ return true;
35
+ }
36
+
25
37
  /**
26
38
  * @param {any} variable
27
39
  * @returns {boolean}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pdfmake",
3
- "version": "0.3.0-beta.7",
3
+ "version": "0.3.0-beta.9",
4
4
  "description": "Client/server side PDF printing in pure JavaScript",
5
5
  "main": "js/index.js",
6
6
  "esnext": "src/index.js",
package/src/DocMeasure.js CHANGED
@@ -433,16 +433,17 @@ class DocMeasure {
433
433
  if (item.listMarker._inlines) {
434
434
  node._gapSize.width = Math.max(node._gapSize.width, item.listMarker._inlines[0].width);
435
435
  }
436
- } // TODO: else - nested lists numbering
436
+
437
+ if (node.reversed) {
438
+ counter--;
439
+ } else {
440
+ counter++;
441
+ }
442
+ }
437
443
 
438
444
  node._minWidth = Math.max(node._minWidth, items[i]._minWidth);
439
445
  node._maxWidth = Math.max(node._maxWidth, items[i]._maxWidth);
440
446
 
441
- if (node.reversed) {
442
- counter--;
443
- } else {
444
- counter++;
445
- }
446
447
  }
447
448
 
448
449
  node._minWidth += node._gapSize.width;
@@ -18,7 +18,6 @@ class DocumentContext extends EventEmitter {
18
18
  this.page = -1;
19
19
 
20
20
  this.snapshots = [];
21
- this.endingCell = null;
22
21
  this.backgroundLength = [];
23
22
 
24
23
  this.addPage(pageSize);
@@ -38,7 +37,6 @@ class DocumentContext extends EventEmitter {
38
37
  availableWidth: this.availableWidth,
39
38
  page: this.page
40
39
  },
41
- endingCell: this.endingCell,
42
40
  lastColumnWidth: this.lastColumnWidth
43
41
  });
44
42
 
@@ -48,9 +46,8 @@ class DocumentContext extends EventEmitter {
48
46
  beginColumn(width, offset, endingCell) {
49
47
  let saved = this.snapshots[this.snapshots.length - 1];
50
48
 
51
- this.calculateBottomMost(saved);
49
+ this.calculateBottomMost(saved, endingCell);
52
50
 
53
- this.endingCell = endingCell;
54
51
  this.page = saved.page;
55
52
  this.x = this.x + this.lastColumnWidth + (offset || 0);
56
53
  this.y = saved.y;
@@ -60,10 +57,9 @@ class DocumentContext extends EventEmitter {
60
57
  this.lastColumnWidth = width;
61
58
  }
62
59
 
63
- calculateBottomMost(destContext) {
64
- if (this.endingCell) {
65
- this.saveContextInEndingCell(this.endingCell);
66
- this.endingCell = null;
60
+ calculateBottomMost(destContext, endingCell) {
61
+ if (endingCell) {
62
+ this.saveContextInEndingCell(endingCell);
67
63
  } else {
68
64
  destContext.bottomMost = bottomMostContext(this, destContext.bottomMost);
69
65
  }
@@ -89,12 +85,11 @@ class DocumentContext extends EventEmitter {
89
85
  };
90
86
  }
91
87
 
92
- completeColumnGroup(height) {
88
+ completeColumnGroup(height, endingCell) {
93
89
  let saved = this.snapshots.pop();
94
90
 
95
- this.calculateBottomMost(saved);
91
+ this.calculateBottomMost(saved, endingCell);
96
92
 
97
- this.endingCell = null;
98
93
  this.x = saved.x;
99
94
 
100
95
  let y = saved.bottomMost.y;
@@ -171,7 +166,6 @@ class DocumentContext extends EventEmitter {
171
166
  availableHeight: this.availableHeight,
172
167
  availableWidth: this.availableWidth,
173
168
  page: this.page,
174
- endingCell: this.endingCell,
175
169
  lastColumnWidth: this.lastColumnWidth
176
170
  });
177
171
  }
@@ -184,7 +178,6 @@ class DocumentContext extends EventEmitter {
184
178
  this.availableWidth = saved.availableWidth;
185
179
  this.availableHeight = saved.availableHeight;
186
180
  this.page = saved.page;
187
- this.endingCell = saved.endingCell;
188
181
  this.lastColumnWidth = saved.lastColumnWidth;
189
182
  }
190
183
 
@@ -495,6 +495,21 @@ class LayoutBuilder {
495
495
  }
496
496
  }
497
497
 
498
+ findStartingSpanCell(arr, i) {
499
+ let requiredColspan = 1;
500
+ for (let index = i - 1; index >= 0; index--) {
501
+ if (!arr[index]._span) {
502
+ if (arr[index].rowSpan > 1 && (arr[index].colSpan || 1) === requiredColspan) {
503
+ return arr[index];
504
+ } else {
505
+ return null;
506
+ }
507
+ }
508
+ requiredColspan++;
509
+ }
510
+ return null;
511
+ }
512
+
498
513
  processRow(columns, widths, gaps, tableBody, tableRow, height) {
499
514
  const storePageBreakData = data => {
500
515
  let pageDesc;
@@ -535,17 +550,52 @@ class LayoutBuilder {
535
550
  }
536
551
  }
537
552
 
538
- this.writer.context().beginColumn(width, leftOffset, getEndingCell(column, i));
553
+ // if rowspan starts in this cell, we retrieve the last cell affected by the rowspan
554
+ const endingCell = getEndingCell(column, i);
555
+ if (endingCell) {
556
+ // We store a reference of the ending cell in the first cell of the rowspan
557
+ column._endingCell = endingCell;
558
+ }
559
+
560
+ // Check if exists and retrieve the cell that started the rowspan in case we are in the cell just after
561
+ let startingSpanCell = this.findStartingSpanCell(columns, i);
562
+ let endingSpanCell = null;
563
+ if (startingSpanCell && startingSpanCell._endingCell) {
564
+ // Reference to the last cell of the rowspan
565
+ endingSpanCell = startingSpanCell._endingCell;
566
+ }
567
+
568
+ // We pass the endingSpanCell reference to store the context just after processing rowspan cell
569
+ this.writer.context().beginColumn(width, leftOffset, endingSpanCell);
539
570
  if (!column._span) {
540
571
  this.processNode(column);
541
572
  addAll(positions, column.positions);
542
573
  } else if (column._columnEndingContext) {
543
574
  // row-span ending
575
+ // Recover the context after processing the rowspanned cell
544
576
  this.writer.context().markEnding(column);
545
577
  }
546
578
  }
547
579
 
548
- this.writer.context().completeColumnGroup(height);
580
+ // Check if last cell is part of a span
581
+ let endingSpanCell = null;
582
+ const lastColumn = columns.length > 0 ? columns[columns.length - 1] : null;
583
+ if (lastColumn) {
584
+ // Previous column cell has a rowspan
585
+ if (lastColumn._endingCell) {
586
+ endingSpanCell = lastColumn._endingCell;
587
+ // Previous column cell is part of a span
588
+ } else if (lastColumn._span === true) {
589
+ // We get the cell that started the span where we set a reference to the ending cell
590
+ const startingSpanCell = this.findStartingSpanCell(columns, columns.length);
591
+ if (startingSpanCell) {
592
+ // Context will be stored here (ending cell)
593
+ endingSpanCell = startingSpanCell._endingCell;
594
+ }
595
+ }
596
+ }
597
+
598
+ this.writer.context().completeColumnGroup(height, endingSpanCell);
549
599
 
550
600
  this.writer.removeListener('pageChanged', storePageBreakData);
551
601