pdfmake 0.2.9 → 0.2.11
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/CHANGELOG.md +12 -0
- package/build/pdfmake.js +3017 -2843
- package/build/pdfmake.js.map +1 -1
- package/build/pdfmake.min.js +2 -2
- package/build/pdfmake.min.js.map +1 -1
- package/package.json +1 -1
- package/src/columnCalculator.js +24 -3
- package/src/docMeasure.js +7 -7
- package/src/documentContext.js +6 -14
- package/src/helpers.js +12 -0
- package/src/layoutBuilder.js +52 -2
- package/src/styleContextStack.js +3 -44
- package/src/tableProcessor.js +22 -5
package/package.json
CHANGED
package/src/columnCalculator.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
var isString = require('./helpers').isString;
|
|
4
4
|
|
|
5
|
-
function buildColumnWidths(columns, availableWidth) {
|
|
5
|
+
function buildColumnWidths(columns, availableWidth, offsetTotal = 0, tableNode) {
|
|
6
6
|
var autoColumns = [],
|
|
7
7
|
autoMin = 0, autoMax = 0,
|
|
8
8
|
starColumns = [],
|
|
@@ -25,10 +25,31 @@ function buildColumnWidths(columns, availableWidth) {
|
|
|
25
25
|
}
|
|
26
26
|
});
|
|
27
27
|
|
|
28
|
-
fixedColumns.forEach(function (col) {
|
|
28
|
+
fixedColumns.forEach(function (col, colIndex) {
|
|
29
29
|
// width specified as %
|
|
30
30
|
if (isString(col.width) && /\d+%/.test(col.width)) {
|
|
31
|
-
|
|
31
|
+
// In tables we have to take into consideration the reserved width for paddings and borders
|
|
32
|
+
var reservedWidth = 0;
|
|
33
|
+
if (tableNode) {
|
|
34
|
+
var paddingLeft = tableNode._layout.paddingLeft(colIndex, tableNode);
|
|
35
|
+
var paddingRight = tableNode._layout.paddingRight(colIndex, tableNode);
|
|
36
|
+
var borderLeft = tableNode._layout.vLineWidth(colIndex, tableNode);
|
|
37
|
+
var 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
|
+
|
|
42
|
+
} else if (colIndex === fixedColumns.length - 1) {
|
|
43
|
+
// last column assumes whole borderRight and half of border left
|
|
44
|
+
reservedWidth = paddingLeft + paddingRight + (borderLeft / 2) + borderRight;
|
|
45
|
+
|
|
46
|
+
} else {
|
|
47
|
+
// Columns in the middle assume half of each border
|
|
48
|
+
reservedWidth = paddingLeft + paddingRight + (borderLeft / 2) + (borderRight / 2);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
var totalAvailableWidth = initial_availableWidth + offsetTotal;
|
|
52
|
+
col.width = (parseFloat(col.width) * totalAvailableWidth / 100) - reservedWidth;
|
|
32
53
|
}
|
|
33
54
|
if (col.width < (col._minWidth) && col.elasticWidth) {
|
|
34
55
|
col._calcWidth = col._minWidth;
|
package/src/docMeasure.js
CHANGED
|
@@ -509,16 +509,16 @@ DocMeasure.prototype.measureOrderedList = function (node) {
|
|
|
509
509
|
if (item.listMarker._inlines) {
|
|
510
510
|
node._gapSize.width = Math.max(node._gapSize.width, item.listMarker._inlines[0].width);
|
|
511
511
|
}
|
|
512
|
-
|
|
512
|
+
|
|
513
|
+
if (node.reversed) {
|
|
514
|
+
counter--;
|
|
515
|
+
} else {
|
|
516
|
+
counter++;
|
|
517
|
+
}
|
|
518
|
+
}
|
|
513
519
|
|
|
514
520
|
node._minWidth = Math.max(node._minWidth, items[i]._minWidth);
|
|
515
521
|
node._maxWidth = Math.max(node._maxWidth, items[i]._maxWidth);
|
|
516
|
-
|
|
517
|
-
if (node.reversed) {
|
|
518
|
-
counter--;
|
|
519
|
-
} else {
|
|
520
|
-
counter++;
|
|
521
|
-
}
|
|
522
522
|
}
|
|
523
523
|
|
|
524
524
|
node._minWidth += node._gapSize.width;
|
package/src/documentContext.js
CHANGED
|
@@ -19,8 +19,6 @@ function DocumentContext(pageSize, pageMargins) {
|
|
|
19
19
|
|
|
20
20
|
this.snapshots = [];
|
|
21
21
|
|
|
22
|
-
this.endingCell = null;
|
|
23
|
-
|
|
24
22
|
this.tracker = new TraversalTracker();
|
|
25
23
|
|
|
26
24
|
this.backgroundLength = [];
|
|
@@ -42,7 +40,6 @@ DocumentContext.prototype.beginColumnGroup = function () {
|
|
|
42
40
|
availableWidth: this.availableWidth,
|
|
43
41
|
page: this.page
|
|
44
42
|
},
|
|
45
|
-
endingCell: this.endingCell,
|
|
46
43
|
lastColumnWidth: this.lastColumnWidth
|
|
47
44
|
});
|
|
48
45
|
|
|
@@ -52,9 +49,8 @@ DocumentContext.prototype.beginColumnGroup = function () {
|
|
|
52
49
|
DocumentContext.prototype.beginColumn = function (width, offset, endingCell) {
|
|
53
50
|
var saved = this.snapshots[this.snapshots.length - 1];
|
|
54
51
|
|
|
55
|
-
this.calculateBottomMost(saved);
|
|
52
|
+
this.calculateBottomMost(saved, endingCell);
|
|
56
53
|
|
|
57
|
-
this.endingCell = endingCell;
|
|
58
54
|
this.page = saved.page;
|
|
59
55
|
this.x = this.x + this.lastColumnWidth + (offset || 0);
|
|
60
56
|
this.y = saved.y;
|
|
@@ -64,10 +60,9 @@ DocumentContext.prototype.beginColumn = function (width, offset, endingCell) {
|
|
|
64
60
|
this.lastColumnWidth = width;
|
|
65
61
|
};
|
|
66
62
|
|
|
67
|
-
DocumentContext.prototype.calculateBottomMost = function (destContext) {
|
|
68
|
-
if (
|
|
69
|
-
this.saveContextInEndingCell(
|
|
70
|
-
this.endingCell = null;
|
|
63
|
+
DocumentContext.prototype.calculateBottomMost = function (destContext, endingCell) {
|
|
64
|
+
if (endingCell) {
|
|
65
|
+
this.saveContextInEndingCell(endingCell);
|
|
71
66
|
} else {
|
|
72
67
|
destContext.bottomMost = bottomMostContext(this, destContext.bottomMost);
|
|
73
68
|
}
|
|
@@ -93,12 +88,11 @@ DocumentContext.prototype.saveContextInEndingCell = function (endingCell) {
|
|
|
93
88
|
};
|
|
94
89
|
};
|
|
95
90
|
|
|
96
|
-
DocumentContext.prototype.completeColumnGroup = function (height) {
|
|
91
|
+
DocumentContext.prototype.completeColumnGroup = function (height, endingCell) {
|
|
97
92
|
var saved = this.snapshots.pop();
|
|
98
93
|
|
|
99
|
-
this.calculateBottomMost(saved);
|
|
94
|
+
this.calculateBottomMost(saved, endingCell);
|
|
100
95
|
|
|
101
|
-
this.endingCell = null;
|
|
102
96
|
this.x = saved.x;
|
|
103
97
|
|
|
104
98
|
var y = saved.bottomMost.y;
|
|
@@ -175,7 +169,6 @@ DocumentContext.prototype.beginDetachedBlock = function () {
|
|
|
175
169
|
availableHeight: this.availableHeight,
|
|
176
170
|
availableWidth: this.availableWidth,
|
|
177
171
|
page: this.page,
|
|
178
|
-
endingCell: this.endingCell,
|
|
179
172
|
lastColumnWidth: this.lastColumnWidth
|
|
180
173
|
});
|
|
181
174
|
};
|
|
@@ -188,7 +181,6 @@ DocumentContext.prototype.endDetachedBlock = function () {
|
|
|
188
181
|
this.availableWidth = saved.availableWidth;
|
|
189
182
|
this.availableHeight = saved.availableHeight;
|
|
190
183
|
this.page = saved.page;
|
|
191
|
-
this.endingCell = saved.endingCell;
|
|
192
184
|
this.lastColumnWidth = saved.lastColumnWidth;
|
|
193
185
|
};
|
|
194
186
|
|
package/src/helpers.js
CHANGED
|
@@ -32,6 +32,17 @@ function isUndefined(variable) {
|
|
|
32
32
|
return variable === undefined;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
/**
|
|
36
|
+
* @param {any} variable
|
|
37
|
+
* @returns {boolean}
|
|
38
|
+
*/
|
|
39
|
+
function isPositiveInteger(variable) {
|
|
40
|
+
if (!isNumber(variable) || !Number.isInteger(variable) || variable <= 0) {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
|
|
35
46
|
function pack() {
|
|
36
47
|
var result = {};
|
|
37
48
|
|
|
@@ -117,6 +128,7 @@ module.exports = {
|
|
|
117
128
|
isObject: isObject,
|
|
118
129
|
isNull: isNull,
|
|
119
130
|
isUndefined: isUndefined,
|
|
131
|
+
isPositiveInteger: isPositiveInteger,
|
|
120
132
|
pack: pack,
|
|
121
133
|
fontStringify: fontStringify,
|
|
122
134
|
offsetVector: offsetVector,
|
package/src/layoutBuilder.js
CHANGED
|
@@ -511,6 +511,21 @@ LayoutBuilder.prototype.processColumns = function (columnNode) {
|
|
|
511
511
|
}
|
|
512
512
|
};
|
|
513
513
|
|
|
514
|
+
LayoutBuilder.prototype.findStartingSpanCell = function (arr, i) {
|
|
515
|
+
let requiredColspan = 1;
|
|
516
|
+
for (let index = i - 1; index >= 0; index--) {
|
|
517
|
+
if (!arr[index]._span) {
|
|
518
|
+
if (arr[index].rowSpan > 1 && (arr[index].colSpan || 1) === requiredColspan) {
|
|
519
|
+
return arr[index];
|
|
520
|
+
} else {
|
|
521
|
+
return null;
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
requiredColspan++;
|
|
525
|
+
}
|
|
526
|
+
return null;
|
|
527
|
+
}
|
|
528
|
+
|
|
514
529
|
LayoutBuilder.prototype.processRow = function (columns, widths, gaps, tableBody, tableRow, height) {
|
|
515
530
|
var self = this;
|
|
516
531
|
var pageBreaks = [], positions = [];
|
|
@@ -531,17 +546,52 @@ LayoutBuilder.prototype.processRow = function (columns, widths, gaps, tableBody,
|
|
|
531
546
|
}
|
|
532
547
|
}
|
|
533
548
|
|
|
534
|
-
|
|
549
|
+
// if rowspan starts in this cell, we retrieve the last cell affected by the rowspan
|
|
550
|
+
var endingCell = getEndingCell(column, i);
|
|
551
|
+
if (endingCell) {
|
|
552
|
+
// We store a reference of the ending cell in the first cell of the rowspan
|
|
553
|
+
column._endingCell = endingCell;
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
// Check if exists and retrieve the cell that started the rowspan in case we are in the cell just after
|
|
557
|
+
var startingSpanCell = self.findStartingSpanCell(columns, i);
|
|
558
|
+
var endingSpanCell = null;
|
|
559
|
+
if (startingSpanCell && startingSpanCell._endingCell) {
|
|
560
|
+
// Reference to the last cell of the rowspan
|
|
561
|
+
endingSpanCell = startingSpanCell._endingCell;
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
// We pass the endingSpanCell reference to store the context just after processing rowspan cell
|
|
565
|
+
self.writer.context().beginColumn(width, leftOffset, endingSpanCell);
|
|
535
566
|
if (!column._span) {
|
|
536
567
|
self.processNode(column);
|
|
537
568
|
addAll(positions, column.positions);
|
|
538
569
|
} else if (column._columnEndingContext) {
|
|
539
570
|
// row-span ending
|
|
571
|
+
// Recover the context after processing the rowspanned cell
|
|
540
572
|
self.writer.context().markEnding(column);
|
|
541
573
|
}
|
|
542
574
|
}
|
|
543
575
|
|
|
544
|
-
|
|
576
|
+
// Check if last cell is part of a span
|
|
577
|
+
var endingSpanCell = null;
|
|
578
|
+
var lastColumn = columns.length > 0 ? columns[columns.length - 1] : null;
|
|
579
|
+
if (lastColumn) {
|
|
580
|
+
// Previous column cell has a rowspan
|
|
581
|
+
if (lastColumn._endingCell) {
|
|
582
|
+
endingSpanCell = lastColumn._endingCell;
|
|
583
|
+
// Previous column cell is part of a span
|
|
584
|
+
} else if (lastColumn._span === true) {
|
|
585
|
+
// We get the cell that started the span where we set a reference to the ending cell
|
|
586
|
+
var startingSpanCell = self.findStartingSpanCell(columns, columns.length);
|
|
587
|
+
if (startingSpanCell) {
|
|
588
|
+
// Context will be stored here (ending cell)
|
|
589
|
+
endingSpanCell = startingSpanCell._endingCell;
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
self.writer.context().completeColumnGroup(height, endingSpanCell);
|
|
545
595
|
});
|
|
546
596
|
|
|
547
597
|
return { pageBreaks: pageBreaks, positions: positions };
|
package/src/styleContextStack.js
CHANGED
|
@@ -84,50 +84,9 @@ StyleContextStack.prototype.autopush = function (item) {
|
|
|
84
84
|
this.push(styleNames[i]);
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
'fontFeatures',
|
|
91
|
-
'bold',
|
|
92
|
-
'italics',
|
|
93
|
-
'alignment',
|
|
94
|
-
'color',
|
|
95
|
-
'columnGap',
|
|
96
|
-
'fillColor',
|
|
97
|
-
'fillOpacity',
|
|
98
|
-
'decoration',
|
|
99
|
-
'decorationStyle',
|
|
100
|
-
'decorationColor',
|
|
101
|
-
'background',
|
|
102
|
-
'lineHeight',
|
|
103
|
-
'characterSpacing',
|
|
104
|
-
'noWrap',
|
|
105
|
-
'markerColor',
|
|
106
|
-
'leadingIndent',
|
|
107
|
-
'sup',
|
|
108
|
-
'sub'
|
|
109
|
-
//'tableCellPadding'
|
|
110
|
-
// 'cellBorder',
|
|
111
|
-
// 'headerCellBorder',
|
|
112
|
-
// 'oddRowCellBorder',
|
|
113
|
-
// 'evenRowCellBorder',
|
|
114
|
-
// 'tableBorder'
|
|
115
|
-
];
|
|
116
|
-
var styleOverrideObject = {};
|
|
117
|
-
var pushStyleOverrideObject = false;
|
|
118
|
-
|
|
119
|
-
styleProperties.forEach(function (key) {
|
|
120
|
-
if (!isUndefined(item[key]) && !isNull(item[key])) {
|
|
121
|
-
styleOverrideObject[key] = item[key];
|
|
122
|
-
pushStyleOverrideObject = true;
|
|
123
|
-
}
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
if (pushStyleOverrideObject) {
|
|
127
|
-
this.push(styleOverrideObject);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
return styleNames.length + (pushStyleOverrideObject ? 1 : 0);
|
|
87
|
+
// rather than spend significant time making a styleOverrideObject, just add item
|
|
88
|
+
this.push(item);
|
|
89
|
+
return styleNames.length + 1;
|
|
131
90
|
};
|
|
132
91
|
|
|
133
92
|
/**
|
package/src/tableProcessor.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
var ColumnCalculator = require('./columnCalculator');
|
|
4
4
|
var isFunction = require('./helpers').isFunction;
|
|
5
5
|
var isNumber = require('./helpers').isNumber;
|
|
6
|
+
var isPositiveInteger = require('./helpers').isPositiveInteger;
|
|
6
7
|
|
|
7
8
|
function TableProcessor(tableNode) {
|
|
8
9
|
this.tableNode = tableNode;
|
|
@@ -18,18 +19,34 @@ TableProcessor.prototype.beginTable = function (writer) {
|
|
|
18
19
|
this.layout = tableNode._layout;
|
|
19
20
|
|
|
20
21
|
availableWidth = writer.context().availableWidth - this.offsets.total;
|
|
21
|
-
ColumnCalculator.buildColumnWidths(tableNode.table.widths, availableWidth);
|
|
22
|
+
ColumnCalculator.buildColumnWidths(tableNode.table.widths, availableWidth, this.offsets.total, tableNode);
|
|
22
23
|
|
|
23
24
|
this.tableWidth = tableNode._offsets.total + getTableInnerContentWidth();
|
|
24
25
|
this.rowSpanData = prepareRowSpanData();
|
|
25
26
|
this.cleanUpRepeatables = false;
|
|
26
27
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
// headersRows and rowsWithoutPageBreak (headerRows + keepWithHeaderRows)
|
|
29
|
+
this.headerRows = 0;
|
|
30
|
+
this.rowsWithoutPageBreak = 0;
|
|
31
|
+
|
|
32
|
+
var headerRows = tableNode.table.headerRows;
|
|
33
|
+
|
|
34
|
+
if (isPositiveInteger(headerRows)) {
|
|
35
|
+
this.headerRows = headerRows;
|
|
36
|
+
|
|
37
|
+
if (this.headerRows > tableNode.table.body.length) {
|
|
38
|
+
throw new Error(`Too few rows in the table. Property headerRows requires at least ${this.headerRows}, contains only ${tableNode.table.body.length}`);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
this.rowsWithoutPageBreak = this.headerRows;
|
|
42
|
+
|
|
43
|
+
const keepWithHeaderRows = tableNode.table.keepWithHeaderRows;
|
|
44
|
+
|
|
45
|
+
if (isPositiveInteger(keepWithHeaderRows)) {
|
|
46
|
+
this.rowsWithoutPageBreak += keepWithHeaderRows;
|
|
47
|
+
}
|
|
30
48
|
}
|
|
31
49
|
|
|
32
|
-
this.rowsWithoutPageBreak = this.headerRows + (tableNode.table.keepWithHeaderRows || 0);
|
|
33
50
|
this.dontBreakRows = tableNode.table.dontBreakRows || false;
|
|
34
51
|
|
|
35
52
|
if (this.rowsWithoutPageBreak) {
|