pdfmake 0.3.2 → 0.3.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.
- package/CHANGELOG.md +18 -0
- package/LICENSE +21 -21
- package/README.md +75 -78
- package/build/fonts/Roboto/Roboto-Italic.ttf +0 -0
- package/build/fonts/Roboto/Roboto-Medium.ttf +0 -0
- package/build/fonts/Roboto/Roboto-MediumItalic.ttf +0 -0
- package/build/fonts/Roboto/Roboto-Regular.ttf +0 -0
- package/build/fonts/Roboto.js +27 -0
- package/build/pdfmake.js +64813 -64584
- package/build/pdfmake.js.map +1 -1
- package/build/pdfmake.min.js +2 -2
- package/build/pdfmake.min.js.map +1 -1
- package/build/standard-fonts/Courier.js +27 -27
- package/build/standard-fonts/Helvetica.js +27 -27
- package/build/standard-fonts/Symbol.js +21 -21
- package/build/standard-fonts/Times.js +27 -27
- package/build/standard-fonts/ZapfDingbats.js +21 -21
- package/build/vfs_fonts.js +5 -5
- package/build-vfs.js +44 -44
- package/fonts/Roboto.js +8 -8
- package/js/3rd-party/svg-to-pdfkit/source.js +1 -1
- package/js/DocMeasure.js +11 -6
- package/js/DocumentContext.js +8 -3
- package/js/ElementWriter.js +42 -16
- package/js/LayoutBuilder.js +144 -78
- package/js/Line.js +16 -16
- package/js/OutputDocument.js +10 -10
- package/js/OutputDocumentServer.js +3 -3
- package/js/PDFDocument.js +3 -3
- package/js/PageElementWriter.js +15 -9
- package/js/Printer.js +28 -28
- package/js/Renderer.js +40 -8
- package/js/SVGMeasure.js +10 -10
- package/js/StyleContextStack.js +74 -51
- package/js/TableProcessor.js +14 -0
- package/js/TextBreaker.js +17 -17
- package/js/TextDecorator.js +12 -3
- package/js/TextInlines.js +34 -33
- package/js/base.js +4 -4
- package/js/browser-extensions/OutputDocumentBrowser.js +24 -24
- package/js/columnCalculator.js +2 -2
- package/js/helpers/node.js +47 -23
- package/js/helpers/variableType.js +18 -18
- package/js/qrEnc.js +38 -38
- package/js/virtual-fs.js +11 -11
- package/package.json +12 -12
- package/src/3rd-party/svg-to-pdfkit/LICENSE +9 -9
- package/src/3rd-party/svg-to-pdfkit/source.js +2745 -2745
- package/src/3rd-party/svg-to-pdfkit.js +3 -3
- package/src/DocMeasure.js +745 -738
- package/src/DocPreprocessor.js +283 -283
- package/src/DocumentContext.js +345 -338
- package/src/ElementWriter.js +441 -417
- package/src/LayoutBuilder.js +1336 -1258
- package/src/Line.js +114 -114
- package/src/OutputDocument.js +64 -64
- package/src/OutputDocumentServer.js +32 -32
- package/src/PDFDocument.js +174 -174
- package/src/PageElementWriter.js +187 -179
- package/src/PageSize.js +53 -53
- package/src/Printer.js +306 -306
- package/src/Renderer.js +445 -409
- package/src/SVGMeasure.js +109 -109
- package/src/StyleContextStack.js +208 -179
- package/src/TableProcessor.js +620 -602
- package/src/TextBreaker.js +168 -168
- package/src/TextDecorator.js +175 -161
- package/src/TextInlines.js +224 -223
- package/src/URLResolver.js +43 -43
- package/src/base.js +70 -70
- package/src/browser-extensions/OutputDocumentBrowser.js +80 -80
- package/src/browser-extensions/fonts/Roboto.js +27 -27
- package/src/browser-extensions/index.js +55 -55
- package/src/browser-extensions/pdfMake.js +1 -1
- package/src/browser-extensions/standard-fonts/Courier.js +27 -27
- package/src/browser-extensions/standard-fonts/Helvetica.js +27 -27
- package/src/browser-extensions/standard-fonts/Symbol.js +21 -21
- package/src/browser-extensions/standard-fonts/Times.js +27 -27
- package/src/browser-extensions/standard-fonts/ZapfDingbats.js +21 -21
- package/src/browser-extensions/virtual-fs-cjs.js +1 -1
- package/src/columnCalculator.js +154 -154
- package/src/helpers/node.js +134 -110
- package/src/helpers/tools.js +44 -44
- package/src/helpers/variableType.js +50 -50
- package/src/index.js +16 -16
- package/src/qrEnc.js +796 -796
- package/src/standardPageSizes.js +52 -52
- package/src/tableLayouts.js +100 -100
- package/src/virtual-fs.js +66 -66
- package/standard-fonts/Courier.js +8 -8
- package/standard-fonts/Helvetica.js +8 -8
- package/standard-fonts/Symbol.js +5 -5
- package/standard-fonts/Times.js +8 -8
- package/standard-fonts/ZapfDingbats.js +5 -5
package/build-vfs.js
CHANGED
|
@@ -1,44 +1,44 @@
|
|
|
1
|
-
const fs = require('fs');
|
|
2
|
-
|
|
3
|
-
const vfsBefore = "var vfs = ";
|
|
4
|
-
const vfsAfter = "; var _global = typeof window === 'object' ? window : typeof global === 'object' ? global : typeof self === 'object' ? self : this; if (typeof _global.pdfMake !== 'undefined' && typeof _global.pdfMake.addVirtualFileSystem !== 'undefined') { _global.pdfMake.addVirtualFileSystem(vfs); } if (typeof module !== 'undefined') { module.exports = vfs; }";
|
|
5
|
-
const sourcePath = process.argv[2];
|
|
6
|
-
const vfsFilename = process.argv[3] ? process.argv[3] : './build/vfs_fonts.js';
|
|
7
|
-
|
|
8
|
-
var vfs = {};
|
|
9
|
-
|
|
10
|
-
if (sourcePath === undefined) {
|
|
11
|
-
console.error('Usage: node build-vfs.js path [filename]');
|
|
12
|
-
console.log('');
|
|
13
|
-
console.log('Parameters:');
|
|
14
|
-
console.log(' path Source path with fonts.');
|
|
15
|
-
console.log(' filename Optional. Output vfs file. Default: ./build/vfs_fonts.js');
|
|
16
|
-
console.log('');
|
|
17
|
-
console.log('Examples:');
|
|
18
|
-
console.log(' node build-vfs.js "examples/fonts"');
|
|
19
|
-
console.log(' node build-vfs.js "examples/fonts" "./build/vfs_fonts.js"');
|
|
20
|
-
return;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
if (!fs.existsSync(sourcePath)) {
|
|
24
|
-
console.error('Source path "' + sourcePath + '" not found.');
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
console.log('Source path:', sourcePath);
|
|
29
|
-
console.log('');
|
|
30
|
-
|
|
31
|
-
var files = fs.readdirSync(sourcePath);
|
|
32
|
-
|
|
33
|
-
files.forEach(function (file) {
|
|
34
|
-
var fileBase64 = fs.readFileSync(sourcePath + '/' + file).toString('base64');
|
|
35
|
-
console.log('FILE:', file);
|
|
36
|
-
|
|
37
|
-
vfs[file] = fileBase64;
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
const vfsFileContent = vfsBefore + JSON.stringify(vfs, null, 2) + vfsAfter;
|
|
41
|
-
fs.writeFileSync(vfsFilename, vfsFileContent);
|
|
42
|
-
|
|
43
|
-
console.log('');
|
|
44
|
-
console.log('Built ' + files.length + ' files to ' + vfsFilename + '.');
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
|
|
3
|
+
const vfsBefore = "var vfs = ";
|
|
4
|
+
const vfsAfter = "; var _global = typeof window === 'object' ? window : typeof global === 'object' ? global : typeof self === 'object' ? self : this; if (typeof _global.pdfMake !== 'undefined' && typeof _global.pdfMake.addVirtualFileSystem !== 'undefined') { _global.pdfMake.addVirtualFileSystem(vfs); } if (typeof module !== 'undefined') { module.exports = vfs; }";
|
|
5
|
+
const sourcePath = process.argv[2];
|
|
6
|
+
const vfsFilename = process.argv[3] ? process.argv[3] : './build/vfs_fonts.js';
|
|
7
|
+
|
|
8
|
+
var vfs = {};
|
|
9
|
+
|
|
10
|
+
if (sourcePath === undefined) {
|
|
11
|
+
console.error('Usage: node build-vfs.js path [filename]');
|
|
12
|
+
console.log('');
|
|
13
|
+
console.log('Parameters:');
|
|
14
|
+
console.log(' path Source path with fonts.');
|
|
15
|
+
console.log(' filename Optional. Output vfs file. Default: ./build/vfs_fonts.js');
|
|
16
|
+
console.log('');
|
|
17
|
+
console.log('Examples:');
|
|
18
|
+
console.log(' node build-vfs.js "examples/fonts"');
|
|
19
|
+
console.log(' node build-vfs.js "examples/fonts" "./build/vfs_fonts.js"');
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (!fs.existsSync(sourcePath)) {
|
|
24
|
+
console.error('Source path "' + sourcePath + '" not found.');
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
console.log('Source path:', sourcePath);
|
|
29
|
+
console.log('');
|
|
30
|
+
|
|
31
|
+
var files = fs.readdirSync(sourcePath);
|
|
32
|
+
|
|
33
|
+
files.forEach(function (file) {
|
|
34
|
+
var fileBase64 = fs.readFileSync(sourcePath + '/' + file).toString('base64');
|
|
35
|
+
console.log('FILE:', file);
|
|
36
|
+
|
|
37
|
+
vfs[file] = fileBase64;
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
const vfsFileContent = vfsBefore + JSON.stringify(vfs, null, 2) + vfsAfter;
|
|
41
|
+
fs.writeFileSync(vfsFilename, vfsFileContent);
|
|
42
|
+
|
|
43
|
+
console.log('');
|
|
44
|
+
console.log('Built ' + files.length + ' files to ' + vfsFilename + '.');
|
package/fonts/Roboto.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
module.exports = {
|
|
2
|
-
Roboto: {
|
|
3
|
-
normal: __dirname + '/Roboto/Roboto-Regular.ttf',
|
|
4
|
-
bold: __dirname + '/Roboto/Roboto-Medium.ttf',
|
|
5
|
-
italics: __dirname + '/Roboto/Roboto-Italic.ttf',
|
|
6
|
-
bolditalics: __dirname + '/Roboto/Roboto-MediumItalic.ttf'
|
|
7
|
-
}
|
|
8
|
-
};
|
|
1
|
+
module.exports = {
|
|
2
|
+
Roboto: {
|
|
3
|
+
normal: __dirname + '/Roboto/Roboto-Regular.ttf',
|
|
4
|
+
bold: __dirname + '/Roboto/Roboto-Medium.ttf',
|
|
5
|
+
italics: __dirname + '/Roboto/Roboto-Italic.ttf',
|
|
6
|
+
bolditalics: __dirname + '/Roboto/Roboto-MediumItalic.ttf'
|
|
7
|
+
}
|
|
8
|
+
};
|
|
@@ -1542,7 +1542,7 @@ var SVGtoPDF = function (doc, svg, x, y, options) {
|
|
|
1542
1542
|
}
|
|
1543
1543
|
}
|
|
1544
1544
|
for (let i = 0; i < selector.classes.length; i++) {
|
|
1545
|
-
if (
|
|
1545
|
+
if (elem.classList.indexOf(selector.classes[i]) === -1) {
|
|
1546
1546
|
return false;
|
|
1547
1547
|
}
|
|
1548
1548
|
}
|
package/js/DocMeasure.js
CHANGED
|
@@ -21,12 +21,12 @@ class DocMeasure {
|
|
|
21
21
|
this.autoImageIndex = 1;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
/**
|
|
25
|
-
* Measures all nodes and sets min/max-width properties required for the second
|
|
26
|
-
* layout-pass.
|
|
27
|
-
*
|
|
28
|
-
* @param {object} docStructure document-definition-object
|
|
29
|
-
* @returns {object} document-measurement-object
|
|
24
|
+
/**
|
|
25
|
+
* Measures all nodes and sets min/max-width properties required for the second
|
|
26
|
+
* layout-pass.
|
|
27
|
+
*
|
|
28
|
+
* @param {object} docStructure document-definition-object
|
|
29
|
+
* @returns {object} document-measurement-object
|
|
30
30
|
*/
|
|
31
31
|
measureDocument(docStructure) {
|
|
32
32
|
return this.measureNode(docStructure);
|
|
@@ -179,6 +179,11 @@ class DocMeasure {
|
|
|
179
179
|
let textStyle = node.toc.textStyle || {};
|
|
180
180
|
let numberStyle = node.toc.numberStyle || textStyle;
|
|
181
181
|
let textMargin = node.toc.textMargin || [0, 0, 0, 0];
|
|
182
|
+
if (node.toc.sortBy === 'title') {
|
|
183
|
+
node.toc._items.sort((a, b) => {
|
|
184
|
+
return a._textNodeRef.text.localeCompare(b._textNodeRef.text, node.toc.sortLocale);
|
|
185
|
+
});
|
|
186
|
+
}
|
|
182
187
|
for (let i = 0, l = node.toc._items.length; i < l; i++) {
|
|
183
188
|
let item = node.toc._items[i];
|
|
184
189
|
let lineStyle = item._textNodeRef.tocStyle || textStyle;
|
package/js/DocumentContext.js
CHANGED
|
@@ -4,9 +4,9 @@ exports.__esModule = true;
|
|
|
4
4
|
exports.default = void 0;
|
|
5
5
|
var _variableType = require("./helpers/variableType");
|
|
6
6
|
var _events = require("events");
|
|
7
|
-
/**
|
|
8
|
-
* A store for current x, y positions and available width/height.
|
|
9
|
-
* It facilitates column divisions and vertical sync
|
|
7
|
+
/**
|
|
8
|
+
* A store for current x, y positions and available width/height.
|
|
9
|
+
* It facilitates column divisions and vertical sync
|
|
10
10
|
*/
|
|
11
11
|
class DocumentContext extends _events.EventEmitter {
|
|
12
12
|
constructor() {
|
|
@@ -110,6 +110,11 @@ class DocumentContext extends _events.EventEmitter {
|
|
|
110
110
|
if (height) {
|
|
111
111
|
this.availableHeight -= y - saved.bottomMost.y;
|
|
112
112
|
}
|
|
113
|
+
if (height && saved.bottomMost.y - saved.y < height) {
|
|
114
|
+
this.height = height;
|
|
115
|
+
} else {
|
|
116
|
+
this.height = saved.bottomMost.y - saved.y;
|
|
117
|
+
}
|
|
113
118
|
this.lastColumnWidth = saved.lastColumnWidth;
|
|
114
119
|
return saved.bottomByPage;
|
|
115
120
|
}
|
package/js/ElementWriter.js
CHANGED
|
@@ -7,13 +7,13 @@ var _tools = require("./helpers/tools");
|
|
|
7
7
|
var _DocumentContext = _interopRequireDefault(require("./DocumentContext"));
|
|
8
8
|
var _events = require("events");
|
|
9
9
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
10
|
-
/**
|
|
11
|
-
* A line/vector writer, which adds elements to current page and sets
|
|
12
|
-
* their positions based on the context
|
|
10
|
+
/**
|
|
11
|
+
* A line/vector writer, which adds elements to current page and sets
|
|
12
|
+
* their positions based on the context
|
|
13
13
|
*/
|
|
14
14
|
class ElementWriter extends _events.EventEmitter {
|
|
15
|
-
/**
|
|
16
|
-
* @param {DocumentContext} context
|
|
15
|
+
/**
|
|
16
|
+
* @param {DocumentContext} context
|
|
17
17
|
*/
|
|
18
18
|
constructor(context) {
|
|
19
19
|
super();
|
|
@@ -21,8 +21,8 @@ class ElementWriter extends _events.EventEmitter {
|
|
|
21
21
|
this.contextStack = [];
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
/**
|
|
25
|
-
* @returns {DocumentContext}
|
|
24
|
+
/**
|
|
25
|
+
* @returns {DocumentContext}
|
|
26
26
|
*/
|
|
27
27
|
context() {
|
|
28
28
|
return this._context;
|
|
@@ -249,6 +249,28 @@ class ElementWriter extends _events.EventEmitter {
|
|
|
249
249
|
});
|
|
250
250
|
return true;
|
|
251
251
|
}
|
|
252
|
+
beginVerticalAlignment(verticalAlignment) {
|
|
253
|
+
let page = this.context().getCurrentPage();
|
|
254
|
+
let item = {
|
|
255
|
+
type: 'beginVerticalAlignment',
|
|
256
|
+
item: {
|
|
257
|
+
verticalAlignment: verticalAlignment
|
|
258
|
+
}
|
|
259
|
+
};
|
|
260
|
+
page.items.push(item);
|
|
261
|
+
return item;
|
|
262
|
+
}
|
|
263
|
+
endVerticalAlignment(verticalAlignment) {
|
|
264
|
+
let page = this.context().getCurrentPage();
|
|
265
|
+
let item = {
|
|
266
|
+
type: 'endVerticalAlignment',
|
|
267
|
+
item: {
|
|
268
|
+
verticalAlignment: verticalAlignment
|
|
269
|
+
}
|
|
270
|
+
};
|
|
271
|
+
page.items.push(item);
|
|
272
|
+
return item;
|
|
273
|
+
}
|
|
252
274
|
addFragment(block, useBlockXOffset, useBlockYOffset, dontUpdateContextPosition) {
|
|
253
275
|
let ctx = this.context();
|
|
254
276
|
let page = ctx.getCurrentPage();
|
|
@@ -290,6 +312,10 @@ class ElementWriter extends _events.EventEmitter {
|
|
|
290
312
|
break;
|
|
291
313
|
case 'image':
|
|
292
314
|
case 'svg':
|
|
315
|
+
case 'beginClip':
|
|
316
|
+
case 'endClip':
|
|
317
|
+
case 'beginVerticalAlignment':
|
|
318
|
+
case 'endVerticalAlignment':
|
|
293
319
|
var img = (0, _tools.pack)(item.item);
|
|
294
320
|
img.x = (img.x || 0) + (useBlockXOffset ? block.xOffset || 0 : ctx.x);
|
|
295
321
|
img.y = (img.y || 0) + (useBlockYOffset ? block.yOffset || 0 : ctx.y);
|
|
@@ -306,15 +332,15 @@ class ElementWriter extends _events.EventEmitter {
|
|
|
306
332
|
return true;
|
|
307
333
|
}
|
|
308
334
|
|
|
309
|
-
/**
|
|
310
|
-
* Pushes the provided context onto the stack or creates a new one
|
|
311
|
-
*
|
|
312
|
-
* pushContext(context) - pushes the provided context and makes it current
|
|
313
|
-
* pushContext(width, height) - creates and pushes a new context with the specified width and height
|
|
314
|
-
* pushContext() - creates a new context for unbreakable blocks (with current availableWidth and full-page-height)
|
|
315
|
-
*
|
|
316
|
-
* @param {DocumentContext|number} contextOrWidth
|
|
317
|
-
* @param {number} height
|
|
335
|
+
/**
|
|
336
|
+
* Pushes the provided context onto the stack or creates a new one
|
|
337
|
+
*
|
|
338
|
+
* pushContext(context) - pushes the provided context and makes it current
|
|
339
|
+
* pushContext(width, height) - creates and pushes a new context with the specified width and height
|
|
340
|
+
* pushContext() - creates a new context for unbreakable blocks (with current availableWidth and full-page-height)
|
|
341
|
+
*
|
|
342
|
+
* @param {DocumentContext|number} contextOrWidth
|
|
343
|
+
* @param {number} height
|
|
318
344
|
*/
|
|
319
345
|
pushContext(contextOrWidth, height) {
|
|
320
346
|
if (contextOrWidth === undefined) {
|
package/js/LayoutBuilder.js
CHANGED
|
@@ -21,15 +21,15 @@ function addAll(target, otherArray) {
|
|
|
21
21
|
});
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
/**
|
|
25
|
-
* Layout engine which turns document-definition-object into a set of pages, lines, inlines
|
|
26
|
-
* and vectors ready to be rendered into a PDF
|
|
24
|
+
/**
|
|
25
|
+
* Layout engine which turns document-definition-object into a set of pages, lines, inlines
|
|
26
|
+
* and vectors ready to be rendered into a PDF
|
|
27
27
|
*/
|
|
28
28
|
class LayoutBuilder {
|
|
29
|
-
/**
|
|
30
|
-
* @param {object} pageSize - an object defining page width and height
|
|
31
|
-
* @param {object} pageMargins - an object defining top, left, right and bottom margins
|
|
32
|
-
* @param {object} svgMeasure
|
|
29
|
+
/**
|
|
30
|
+
* @param {object} pageSize - an object defining page width and height
|
|
31
|
+
* @param {object} pageMargins - an object defining top, left, right and bottom margins
|
|
32
|
+
* @param {object} svgMeasure
|
|
33
33
|
*/
|
|
34
34
|
constructor(pageSize, pageMargins, svgMeasure) {
|
|
35
35
|
this.pageSize = pageSize;
|
|
@@ -37,25 +37,26 @@ class LayoutBuilder {
|
|
|
37
37
|
this.svgMeasure = svgMeasure;
|
|
38
38
|
this.tableLayouts = {};
|
|
39
39
|
this.nestedLevel = 0;
|
|
40
|
+
this.verticalAlignmentItemStack = [];
|
|
40
41
|
}
|
|
41
42
|
registerTableLayouts(tableLayouts) {
|
|
42
43
|
this.tableLayouts = (0, _tools.pack)(this.tableLayouts, tableLayouts);
|
|
43
44
|
}
|
|
44
45
|
|
|
45
|
-
/**
|
|
46
|
-
* Executes layout engine on document-definition-object and creates an array of pages
|
|
47
|
-
* containing positioned Blocks, Lines and inlines
|
|
48
|
-
*
|
|
49
|
-
* @param {object} docStructure document-definition-object
|
|
50
|
-
* @param {object} pdfDocument pdfkit document
|
|
51
|
-
* @param {object} styleDictionary dictionary with style definitions
|
|
52
|
-
* @param {object} defaultStyle default style definition
|
|
53
|
-
* @param {object} background
|
|
54
|
-
* @param {object} header
|
|
55
|
-
* @param {object} footer
|
|
56
|
-
* @param {object} watermark
|
|
57
|
-
* @param {object} pageBreakBeforeFct
|
|
58
|
-
* @returns {Array} an array of pages
|
|
46
|
+
/**
|
|
47
|
+
* Executes layout engine on document-definition-object and creates an array of pages
|
|
48
|
+
* containing positioned Blocks, Lines and inlines
|
|
49
|
+
*
|
|
50
|
+
* @param {object} docStructure document-definition-object
|
|
51
|
+
* @param {object} pdfDocument pdfkit document
|
|
52
|
+
* @param {object} styleDictionary dictionary with style definitions
|
|
53
|
+
* @param {object} defaultStyle default style definition
|
|
54
|
+
* @param {object} background
|
|
55
|
+
* @param {object} header
|
|
56
|
+
* @param {object} footer
|
|
57
|
+
* @param {object} watermark
|
|
58
|
+
* @param {object} pageBreakBeforeFct
|
|
59
|
+
* @returns {Array} an array of pages
|
|
59
60
|
*/
|
|
60
61
|
layoutDocument(docStructure, pdfDocument, styleDictionary, defaultStyle, background, header, footer, watermark, pageBreakBeforeFct) {
|
|
61
62
|
function addPageBreaksIfNecessary(linearNodeList, pages) {
|
|
@@ -296,10 +297,10 @@ class LayoutBuilder {
|
|
|
296
297
|
});
|
|
297
298
|
let rotatedSize;
|
|
298
299
|
|
|
299
|
-
/**
|
|
300
|
-
* Binary search the best font size.
|
|
301
|
-
* Initial bounds [0, 1000]
|
|
302
|
-
* Break when range < 1
|
|
300
|
+
/**
|
|
301
|
+
* Binary search the best font size.
|
|
302
|
+
* Initial bounds [0, 1000]
|
|
303
|
+
* Break when range < 1
|
|
303
304
|
*/
|
|
304
305
|
let a = 0;
|
|
305
306
|
let b = 1000;
|
|
@@ -323,13 +324,13 @@ class LayoutBuilder {
|
|
|
323
324
|
}
|
|
324
325
|
styleContextStack.pop();
|
|
325
326
|
}
|
|
326
|
-
/*
|
|
327
|
-
End binary search
|
|
327
|
+
/*
|
|
328
|
+
End binary search
|
|
328
329
|
*/
|
|
329
330
|
return c;
|
|
330
331
|
}
|
|
331
332
|
}
|
|
332
|
-
processNode(node) {
|
|
333
|
+
processNode(node, isVerticalAlignmentAllowed = false) {
|
|
333
334
|
const applyMargins = callback => {
|
|
334
335
|
let margin = node._margin;
|
|
335
336
|
if (node.pageBreak === 'before') {
|
|
@@ -356,11 +357,11 @@ class LayoutBuilder {
|
|
|
356
357
|
// Consume the whole available space
|
|
357
358
|
this.writer.context().moveDown(availableHeight);
|
|
358
359
|
this.writer.moveToNextPage(node.pageOrientation);
|
|
359
|
-
/**
|
|
360
|
-
* TODO - Something to consider:
|
|
361
|
-
* Right now the node starts at the top of next page (after header)
|
|
362
|
-
* Another option would be to apply just the top margin that has not been consumed in the page before
|
|
363
|
-
* It would something like: this.write.context().moveDown(margin[1] - availableHeight)
|
|
360
|
+
/**
|
|
361
|
+
* TODO - Something to consider:
|
|
362
|
+
* Right now the node starts at the top of next page (after header)
|
|
363
|
+
* Another option would be to apply just the top margin that has not been consumed in the page before
|
|
364
|
+
* It would something like: this.write.context().moveDown(margin[1] - availableHeight)
|
|
364
365
|
*/
|
|
365
366
|
} else {
|
|
366
367
|
this.writer.context().moveDown(margin[1]);
|
|
@@ -378,11 +379,11 @@ class LayoutBuilder {
|
|
|
378
379
|
if (availableHeight - margin[3] < 0) {
|
|
379
380
|
this.writer.context().moveDown(availableHeight);
|
|
380
381
|
this.writer.moveToNextPage(node.pageOrientation);
|
|
381
|
-
/**
|
|
382
|
-
* TODO - Something to consider:
|
|
383
|
-
* Right now next node starts at the top of next page (after header)
|
|
384
|
-
* Another option would be to apply the bottom margin that has not been consumed in the next page?
|
|
385
|
-
* It would something like: this.write.context().moveDown(margin[3] - availableHeight)
|
|
382
|
+
/**
|
|
383
|
+
* TODO - Something to consider:
|
|
384
|
+
* Right now next node starts at the top of next page (after header)
|
|
385
|
+
* Another option would be to apply the bottom margin that has not been consumed in the next page?
|
|
386
|
+
* It would something like: this.write.context().moveDown(margin[3] - availableHeight)
|
|
386
387
|
*/
|
|
387
388
|
} else {
|
|
388
389
|
this.writer.context().moveDown(margin[3]);
|
|
@@ -406,7 +407,14 @@ class LayoutBuilder {
|
|
|
406
407
|
};
|
|
407
408
|
this.linearNodeList.push(node);
|
|
408
409
|
decorateNode(node);
|
|
410
|
+
if (this.writer.context().getCurrentPage() !== null) {
|
|
411
|
+
var prevTop = this.writer.context().getCurrentPosition().top;
|
|
412
|
+
}
|
|
409
413
|
applyMargins(() => {
|
|
414
|
+
let verticalAlignment = node.verticalAlignment;
|
|
415
|
+
if (isVerticalAlignmentAllowed && verticalAlignment) {
|
|
416
|
+
var verticalAlignmentBegin = this.writer.beginVerticalAlignment(verticalAlignment);
|
|
417
|
+
}
|
|
410
418
|
let unbreakable = node.unbreakable;
|
|
411
419
|
if (unbreakable) {
|
|
412
420
|
this.writer.beginUnbreakableBlock();
|
|
@@ -456,7 +464,17 @@ class LayoutBuilder {
|
|
|
456
464
|
if (unbreakable) {
|
|
457
465
|
this.writer.commitUnbreakableBlock();
|
|
458
466
|
}
|
|
467
|
+
if (isVerticalAlignmentAllowed && verticalAlignment) {
|
|
468
|
+
this.verticalAlignmentItemStack.push({
|
|
469
|
+
begin: verticalAlignmentBegin,
|
|
470
|
+
end: this.writer.endVerticalAlignment(verticalAlignment)
|
|
471
|
+
});
|
|
472
|
+
}
|
|
459
473
|
});
|
|
474
|
+
if (prevTop !== undefined) {
|
|
475
|
+
// TODO: for vertical alignment and does not work (at least) when page break in node
|
|
476
|
+
node.__height = this.writer.context().getCurrentPosition().top - prevTop;
|
|
477
|
+
}
|
|
460
478
|
}
|
|
461
479
|
|
|
462
480
|
// vertical container
|
|
@@ -559,13 +577,13 @@ class LayoutBuilder {
|
|
|
559
577
|
}
|
|
560
578
|
}
|
|
561
579
|
|
|
562
|
-
/**
|
|
563
|
-
* Searches for a cell in the same row that starts a rowspan and is positioned immediately before the current cell.
|
|
564
|
-
* Alternatively, it finds a cell where the colspan initiating the rowspan extends to the cell just before the current one.
|
|
565
|
-
*
|
|
566
|
-
* @param {Array<object>} arr - An array representing cells in a row.
|
|
567
|
-
* @param {number} i - The index of the current cell to search backward from.
|
|
568
|
-
* @returns {object|null} The starting cell of the rowspan if found; otherwise, `null`.
|
|
580
|
+
/**
|
|
581
|
+
* Searches for a cell in the same row that starts a rowspan and is positioned immediately before the current cell.
|
|
582
|
+
* Alternatively, it finds a cell where the colspan initiating the rowspan extends to the cell just before the current one.
|
|
583
|
+
*
|
|
584
|
+
* @param {Array<object>} arr - An array representing cells in a row.
|
|
585
|
+
* @param {number} i - The index of the current cell to search backward from.
|
|
586
|
+
* @returns {object|null} The starting cell of the rowspan if found; otherwise, `null`.
|
|
569
587
|
*/
|
|
570
588
|
_findStartingRowSpanCell(arr, i) {
|
|
571
589
|
let requiredColspan = 1;
|
|
@@ -582,12 +600,12 @@ class LayoutBuilder {
|
|
|
582
600
|
return null;
|
|
583
601
|
}
|
|
584
602
|
|
|
585
|
-
/**
|
|
586
|
-
* Retrieves a page break description for a specified page from a list of page breaks.
|
|
587
|
-
*
|
|
588
|
-
* @param {Array<object>} pageBreaks - An array of page break descriptions, each containing `prevPage` properties.
|
|
589
|
-
* @param {number} page - The page number to find the associated page break for.
|
|
590
|
-
* @returns {object|undefined} The page break description object for the specified page if found; otherwise, `undefined`.
|
|
603
|
+
/**
|
|
604
|
+
* Retrieves a page break description for a specified page from a list of page breaks.
|
|
605
|
+
*
|
|
606
|
+
* @param {Array<object>} pageBreaks - An array of page break descriptions, each containing `prevPage` properties.
|
|
607
|
+
* @param {number} page - The page number to find the associated page break for.
|
|
608
|
+
* @returns {object|undefined} The page break description object for the specified page if found; otherwise, `undefined`.
|
|
591
609
|
*/
|
|
592
610
|
_getPageBreak(pageBreaks, page) {
|
|
593
611
|
return pageBreaks.find(desc => desc.prevPage === page);
|
|
@@ -633,14 +651,14 @@ class LayoutBuilder {
|
|
|
633
651
|
});
|
|
634
652
|
}
|
|
635
653
|
|
|
636
|
-
/**
|
|
637
|
-
* Resolves the Y-coordinates for a target object by comparing two break points.
|
|
638
|
-
*
|
|
639
|
-
* @param {object} break1 - The first break point with `prevY` and `y` properties.
|
|
640
|
-
* @param {object} break2 - The second break point with `prevY` and `y` properties.
|
|
641
|
-
* @param {object} target - The target object to be updated with resolved Y-coordinates.
|
|
642
|
-
* @property {number} target.prevY - Updated to the maximum `prevY` value between `break1` and `break2`.
|
|
643
|
-
* @property {number} target.y - Updated to the minimum `y` value between `break1` and `break2`.
|
|
654
|
+
/**
|
|
655
|
+
* Resolves the Y-coordinates for a target object by comparing two break points.
|
|
656
|
+
*
|
|
657
|
+
* @param {object} break1 - The first break point with `prevY` and `y` properties.
|
|
658
|
+
* @param {object} break2 - The second break point with `prevY` and `y` properties.
|
|
659
|
+
* @param {object} target - The target object to be updated with resolved Y-coordinates.
|
|
660
|
+
* @property {number} target.prevY - Updated to the maximum `prevY` value between `break1` and `break2`.
|
|
661
|
+
* @property {number} target.y - Updated to the minimum `y` value between `break1` and `break2`.
|
|
644
662
|
*/
|
|
645
663
|
_resolveBreakY(break1, break2, target) {
|
|
646
664
|
target.prevY = Math.max(break1.prevY, break2.prevY);
|
|
@@ -681,12 +699,12 @@ class LayoutBuilder {
|
|
|
681
699
|
}
|
|
682
700
|
}
|
|
683
701
|
}
|
|
684
|
-
/**
|
|
685
|
-
* Calculates the left offset for a column based on the specified gap values.
|
|
686
|
-
*
|
|
687
|
-
* @param {number} i - The index of the column for which the offset is being calculated.
|
|
688
|
-
* @param {Array<number>} gaps - An array of gap values for each column.
|
|
689
|
-
* @returns {number} The left offset for the column. Returns `gaps[i]` if it exists, otherwise `0`.
|
|
702
|
+
/**
|
|
703
|
+
* Calculates the left offset for a column based on the specified gap values.
|
|
704
|
+
*
|
|
705
|
+
* @param {number} i - The index of the column for which the offset is being calculated.
|
|
706
|
+
* @param {Array<number>} gaps - An array of gap values for each column.
|
|
707
|
+
* @returns {number} The left offset for the column. Returns `gaps[i]` if it exists, otherwise `0`.
|
|
690
708
|
*/
|
|
691
709
|
_colLeftOffset(i, gaps) {
|
|
692
710
|
if (gaps && gaps.length > i) {
|
|
@@ -695,15 +713,15 @@ class LayoutBuilder {
|
|
|
695
713
|
return 0;
|
|
696
714
|
}
|
|
697
715
|
|
|
698
|
-
/**
|
|
699
|
-
* Retrieves the ending cell for a row span in case it exists in a specified table column.
|
|
700
|
-
*
|
|
701
|
-
* @param {Array<Array<object>>} tableBody - The table body, represented as a 2D array of cell objects.
|
|
702
|
-
* @param {number} rowIndex - The index of the starting row for the row span.
|
|
703
|
-
* @param {object} column - The column object containing row span information.
|
|
704
|
-
* @param {number} columnIndex - The index of the column within the row.
|
|
705
|
-
* @returns {object|null} The cell at the end of the row span if it exists; otherwise, `null`.
|
|
706
|
-
* @throws {Error} If the row span extends beyond the total row count.
|
|
716
|
+
/**
|
|
717
|
+
* Retrieves the ending cell for a row span in case it exists in a specified table column.
|
|
718
|
+
*
|
|
719
|
+
* @param {Array<Array<object>>} tableBody - The table body, represented as a 2D array of cell objects.
|
|
720
|
+
* @param {number} rowIndex - The index of the starting row for the row span.
|
|
721
|
+
* @param {object} column - The column object containing row span information.
|
|
722
|
+
* @param {number} columnIndex - The index of the column within the row.
|
|
723
|
+
* @returns {object|null} The cell at the end of the row span if it exists; otherwise, `null`.
|
|
724
|
+
* @throws {Error} If the row span extends beyond the total row count.
|
|
707
725
|
*/
|
|
708
726
|
_getRowSpanEndingCell(tableBody, rowIndex, column, columnIndex) {
|
|
709
727
|
if (column.rowSpan && column.rowSpan > 1) {
|
|
@@ -732,6 +750,7 @@ class LayoutBuilder {
|
|
|
732
750
|
let pageBreaksByRowSpan = [];
|
|
733
751
|
let positions = [];
|
|
734
752
|
let willBreakByHeight = false;
|
|
753
|
+
let verticalAlignmentCells = {};
|
|
735
754
|
widths = widths || cells;
|
|
736
755
|
|
|
737
756
|
// Check if row should break by height
|
|
@@ -745,6 +764,7 @@ class LayoutBuilder {
|
|
|
745
764
|
this.writer.context().beginColumnGroup(marginXParent, _bottomByPage);
|
|
746
765
|
for (let i = 0, l = cells.length; i < l; i++) {
|
|
747
766
|
let cell = cells[i];
|
|
767
|
+
let cellIndexBegin = i;
|
|
748
768
|
|
|
749
769
|
// Page change handler
|
|
750
770
|
const storePageBreakClosure = data => {
|
|
@@ -767,12 +787,18 @@ class LayoutBuilder {
|
|
|
767
787
|
}
|
|
768
788
|
|
|
769
789
|
// if rowspan starts in this cell, we retrieve the last cell affected by the rowspan
|
|
770
|
-
const
|
|
771
|
-
|
|
790
|
+
const rowSpanRightEndingCell = this._getRowSpanEndingCell(tableBody, rowIndex, cell, i);
|
|
791
|
+
const rowSpanLeftEndingCell = this._getRowSpanEndingCell(tableBody, rowIndex, cell, cellIndexBegin);
|
|
792
|
+
if (rowSpanRightEndingCell) {
|
|
772
793
|
// We store a reference of the ending cell in the first cell of the rowspan
|
|
773
|
-
cell._endingCell =
|
|
794
|
+
cell._endingCell = rowSpanRightEndingCell;
|
|
774
795
|
cell._endingCell._startingRowSpanY = cell._startingRowSpanY;
|
|
775
796
|
}
|
|
797
|
+
if (rowSpanLeftEndingCell) {
|
|
798
|
+
// We store a reference of the left ending cell in the first cell of the rowspan
|
|
799
|
+
cell._leftEndingCell = rowSpanLeftEndingCell;
|
|
800
|
+
cell._leftEndingCell._startingRowSpanY = cell._startingRowSpanY;
|
|
801
|
+
}
|
|
776
802
|
|
|
777
803
|
// If we are after a cell that started a rowspan
|
|
778
804
|
let endOfRowSpanCell = null;
|
|
@@ -789,8 +815,11 @@ class LayoutBuilder {
|
|
|
789
815
|
// We pass the endingSpanCell reference to store the context just after processing rowspan cell
|
|
790
816
|
this.writer.context().beginColumn(width, leftOffset, endOfRowSpanCell);
|
|
791
817
|
if (!cell._span) {
|
|
792
|
-
this.processNode(cell);
|
|
818
|
+
this.processNode(cell, true);
|
|
793
819
|
this.writer.context().updateBottomByPage();
|
|
820
|
+
if (cell.verticalAlignment) {
|
|
821
|
+
verticalAlignmentCells[cellIndexBegin] = this.verticalAlignmentItemStack.length - 1;
|
|
822
|
+
}
|
|
794
823
|
addAll(positions, cell.positions);
|
|
795
824
|
} else if (cell._columnEndingContext) {
|
|
796
825
|
let discountY = 0;
|
|
@@ -846,6 +875,40 @@ class LayoutBuilder {
|
|
|
846
875
|
// If there are page breaks in this row, update data with prevY of last cell
|
|
847
876
|
this._updatePageBreaksData(pageBreaks, tableNode, rowIndex);
|
|
848
877
|
}
|
|
878
|
+
let rowHeight = this.writer.context().height;
|
|
879
|
+
for (let i = 0, l = cells.length; i < l; i++) {
|
|
880
|
+
let cell = cells[i];
|
|
881
|
+
if (!cell._span && cell.verticalAlignment) {
|
|
882
|
+
let itemBegin = this.verticalAlignmentItemStack[verticalAlignmentCells[i]].begin.item;
|
|
883
|
+
itemBegin.viewHeight = rowHeight;
|
|
884
|
+
itemBegin.nodeHeight = cell.__height;
|
|
885
|
+
itemBegin.cell = cell;
|
|
886
|
+
itemBegin.bottomY = this.writer.context().y;
|
|
887
|
+
itemBegin.isCellContentMultiPage = !itemBegin.cell.positions.every(item => item.pageNumber === itemBegin.cell.positions[0].pageNumber);
|
|
888
|
+
itemBegin.getViewHeight = function () {
|
|
889
|
+
if (this.cell._willBreak) {
|
|
890
|
+
return this.cell._bottomY - this.cell._rowTopPageY;
|
|
891
|
+
}
|
|
892
|
+
if (this.cell.rowSpan && this.cell.rowSpan > 1) {
|
|
893
|
+
if (dontBreakRows) {
|
|
894
|
+
let rowTopPageY = this.cell._leftEndingCell._startingRowSpanY + this.cell._leftEndingCell._rowTopPageYPadding;
|
|
895
|
+
return this.cell._leftEndingCell._rowTopPageY - rowTopPageY + this.cell._leftEndingCell._bottomY;
|
|
896
|
+
} else {
|
|
897
|
+
if (this.cell.positions[0].pageNumber !== this.cell._leftEndingCell._lastPageNumber) {
|
|
898
|
+
return this.bottomY - this.cell._leftEndingCell._bottomY;
|
|
899
|
+
}
|
|
900
|
+
return this.viewHeight + this.cell._leftEndingCell._bottomY - this.bottomY;
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
return this.viewHeight;
|
|
904
|
+
};
|
|
905
|
+
itemBegin.getNodeHeight = function () {
|
|
906
|
+
return this.nodeHeight;
|
|
907
|
+
};
|
|
908
|
+
let itemEnd = this.verticalAlignmentItemStack[verticalAlignmentCells[i]].end.item;
|
|
909
|
+
itemEnd.isCellContentMultiPage = itemBegin.isCellContentMultiPage;
|
|
910
|
+
}
|
|
911
|
+
}
|
|
849
912
|
return {
|
|
850
913
|
pageBreaksBySpan: pageBreaksByRowSpan,
|
|
851
914
|
pageBreaks: pageBreaks,
|
|
@@ -987,6 +1050,9 @@ class LayoutBuilder {
|
|
|
987
1050
|
}
|
|
988
1051
|
}
|
|
989
1052
|
processToc(node) {
|
|
1053
|
+
if (!node.toc._table && node.toc.hideEmpty === true) {
|
|
1054
|
+
return;
|
|
1055
|
+
}
|
|
990
1056
|
if (node.toc.title) {
|
|
991
1057
|
this.processNode(node.toc.title);
|
|
992
1058
|
}
|