pdfmake 0.3.0-beta.17 → 0.3.0-beta.18
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 +6 -0
- package/README.md +1 -0
- package/build/pdfmake.js +6808 -6661
- package/build/pdfmake.js.map +1 -1
- package/build/pdfmake.min.js +2 -2
- package/build/pdfmake.min.js.map +1 -1
- package/js/DocMeasure.js +12 -1
- package/js/DocPreprocessor.js +21 -6
- package/js/DocumentContext.js +5 -4
- package/js/LayoutBuilder.js +127 -33
- package/js/PageElementWriter.js +2 -2
- package/js/Printer.js +3 -1
- package/js/StyleContextStack.js +4 -0
- package/package.json +13 -13
- package/src/DocMeasure.js +15 -1
- package/src/DocPreprocessor.js +25 -6
- package/src/DocumentContext.js +4 -4
- package/src/LayoutBuilder.js +158 -38
- package/src/PageElementWriter.js +2 -2
- package/src/Printer.js +3 -1
- package/src/StyleContextStack.js +4 -0
package/js/DocMeasure.js
CHANGED
|
@@ -31,11 +31,16 @@ class DocMeasure {
|
|
|
31
31
|
measureDocument(docStructure) {
|
|
32
32
|
return this.measureNode(docStructure);
|
|
33
33
|
}
|
|
34
|
+
measureBlock(node) {
|
|
35
|
+
return this.measureNode(node);
|
|
36
|
+
}
|
|
34
37
|
measureNode(node) {
|
|
35
38
|
return this.styleStack.auto(node, () => {
|
|
36
39
|
// TODO: refactor + rethink whether this is the proper way to handle margins
|
|
37
40
|
node._margin = (0, _node.getNodeMargin)(node, this.styleStack);
|
|
38
|
-
if (node.
|
|
41
|
+
if (node.section) {
|
|
42
|
+
return extendMargins(this.measureSection(node));
|
|
43
|
+
} else if (node.columns) {
|
|
39
44
|
return extendMargins(this.measureColumns(node));
|
|
40
45
|
} else if (node.stack) {
|
|
41
46
|
return extendMargins(this.measureVerticalContainer(node));
|
|
@@ -423,6 +428,12 @@ class DocMeasure {
|
|
|
423
428
|
}
|
|
424
429
|
return node;
|
|
425
430
|
}
|
|
431
|
+
measureSection(node) {
|
|
432
|
+
// TODO: properties
|
|
433
|
+
|
|
434
|
+
node.section = this.measureNode(node.section);
|
|
435
|
+
return node;
|
|
436
|
+
}
|
|
426
437
|
measureColumns(node) {
|
|
427
438
|
let columns = node.columns;
|
|
428
439
|
node._gap = this.styleStack.getProperty('columnGap') || 0;
|
package/js/DocPreprocessor.js
CHANGED
|
@@ -22,9 +22,15 @@ class DocPreprocessor {
|
|
|
22
22
|
this.parentNode = null;
|
|
23
23
|
this.tocs = [];
|
|
24
24
|
this.nodeReferences = [];
|
|
25
|
-
return this.preprocessNode(docStructure);
|
|
25
|
+
return this.preprocessNode(docStructure, true);
|
|
26
26
|
}
|
|
27
|
-
|
|
27
|
+
preprocessBlock(node) {
|
|
28
|
+
this.parentNode = null;
|
|
29
|
+
this.tocs = [];
|
|
30
|
+
this.nodeReferences = [];
|
|
31
|
+
return this.preprocessNode(node);
|
|
32
|
+
}
|
|
33
|
+
preprocessNode(node, isSectionAllowed = false) {
|
|
28
34
|
// expand shortcuts and casting values
|
|
29
35
|
if (Array.isArray(node)) {
|
|
30
36
|
node = {
|
|
@@ -39,10 +45,15 @@ class DocPreprocessor {
|
|
|
39
45
|
// cast value in text property
|
|
40
46
|
node.text = convertValueToString(node.text);
|
|
41
47
|
}
|
|
42
|
-
if (node.
|
|
48
|
+
if (node.section) {
|
|
49
|
+
if (!isSectionAllowed) {
|
|
50
|
+
throw new Error(`Incorrect document structure, section node is only allowed at the root level of document structure: ${(0, _node.stringifyNode)(node)}`);
|
|
51
|
+
}
|
|
52
|
+
return this.preprocessSection(node);
|
|
53
|
+
} else if (node.columns) {
|
|
43
54
|
return this.preprocessColumns(node);
|
|
44
55
|
} else if (node.stack) {
|
|
45
|
-
return this.preprocessVerticalContainer(node);
|
|
56
|
+
return this.preprocessVerticalContainer(node, isSectionAllowed);
|
|
46
57
|
} else if (node.ul) {
|
|
47
58
|
return this.preprocessList(node);
|
|
48
59
|
} else if (node.ol) {
|
|
@@ -69,6 +80,10 @@ class DocPreprocessor {
|
|
|
69
80
|
throw new Error(`Unrecognized document structure: ${(0, _node.stringifyNode)(node)}`);
|
|
70
81
|
}
|
|
71
82
|
}
|
|
83
|
+
preprocessSection(node) {
|
|
84
|
+
node.section = this.preprocessNode(node.section);
|
|
85
|
+
return node;
|
|
86
|
+
}
|
|
72
87
|
preprocessColumns(node) {
|
|
73
88
|
let columns = node.columns;
|
|
74
89
|
for (let i = 0, l = columns.length; i < l; i++) {
|
|
@@ -76,10 +91,10 @@ class DocPreprocessor {
|
|
|
76
91
|
}
|
|
77
92
|
return node;
|
|
78
93
|
}
|
|
79
|
-
preprocessVerticalContainer(node) {
|
|
94
|
+
preprocessVerticalContainer(node, isSectionAllowed) {
|
|
80
95
|
let items = node.stack;
|
|
81
96
|
for (let i = 0, l = items.length; i < l; i++) {
|
|
82
|
-
items[i] = this.preprocessNode(items[i]);
|
|
97
|
+
items[i] = this.preprocessNode(items[i], isSectionAllowed);
|
|
83
98
|
}
|
|
84
99
|
return node;
|
|
85
100
|
}
|
package/js/DocumentContext.js
CHANGED
|
@@ -204,7 +204,7 @@ class DocumentContext extends _events.EventEmitter {
|
|
|
204
204
|
let currentAvailableWidth = this.availableWidth;
|
|
205
205
|
let currentPageOrientation = this.getCurrentPage().pageSize.orientation;
|
|
206
206
|
let pageSize = getPageSize(this.getCurrentPage(), pageOrientation);
|
|
207
|
-
this.addPage(pageSize);
|
|
207
|
+
this.addPage(pageSize, null, this.getCurrentPage().customProperties);
|
|
208
208
|
if (currentPageOrientation === pageSize.orientation) {
|
|
209
209
|
this.availableWidth = currentAvailableWidth;
|
|
210
210
|
}
|
|
@@ -219,7 +219,7 @@ class DocumentContext extends _events.EventEmitter {
|
|
|
219
219
|
y: this.y
|
|
220
220
|
};
|
|
221
221
|
}
|
|
222
|
-
addPage(pageSize, pageMargin = null) {
|
|
222
|
+
addPage(pageSize, pageMargin = null, customProperties = {}) {
|
|
223
223
|
if (pageMargin !== null) {
|
|
224
224
|
this.pageMargins = pageMargin;
|
|
225
225
|
this.x = pageMargin.left;
|
|
@@ -228,13 +228,14 @@ class DocumentContext extends _events.EventEmitter {
|
|
|
228
228
|
let page = {
|
|
229
229
|
items: [],
|
|
230
230
|
pageSize: pageSize,
|
|
231
|
-
pageMargins: this.pageMargins
|
|
231
|
+
pageMargins: this.pageMargins,
|
|
232
|
+
customProperties: customProperties
|
|
232
233
|
};
|
|
233
234
|
this.pages.push(page);
|
|
234
235
|
this.backgroundLength.push(0);
|
|
235
236
|
this.page = this.pages.length - 1;
|
|
236
237
|
this.initializePage();
|
|
237
|
-
this.emit('pageAdded');
|
|
238
|
+
this.emit('pageAdded', page);
|
|
238
239
|
return page;
|
|
239
240
|
}
|
|
240
241
|
getCurrentPage() {
|
package/js/LayoutBuilder.js
CHANGED
|
@@ -132,19 +132,31 @@ class LayoutBuilder {
|
|
|
132
132
|
return result.pages;
|
|
133
133
|
}
|
|
134
134
|
tryLayoutDocument(docStructure, pdfDocument, styleDictionary, defaultStyle, background, header, footer, watermark) {
|
|
135
|
+
const isNecessaryAddFirstPage = docStructure => {
|
|
136
|
+
if (docStructure.stack && docStructure.stack.length > 0 && docStructure.stack[0].section) {
|
|
137
|
+
return false;
|
|
138
|
+
} else if (docStructure.section) {
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
return true;
|
|
142
|
+
};
|
|
135
143
|
this.linearNodeList = [];
|
|
136
144
|
docStructure = this.docPreprocessor.preprocessDocument(docStructure);
|
|
137
145
|
docStructure = this.docMeasure.measureDocument(docStructure);
|
|
138
146
|
this.writer = new _PageElementWriter.default(new _DocumentContext.default());
|
|
139
|
-
this.writer.context().addListener('pageAdded',
|
|
140
|
-
|
|
147
|
+
this.writer.context().addListener('pageAdded', page => {
|
|
148
|
+
let backgroundGetter = background;
|
|
149
|
+
if (page.customProperties['background'] || page.customProperties['background'] === null) {
|
|
150
|
+
backgroundGetter = page.customProperties['background'];
|
|
151
|
+
}
|
|
152
|
+
this.addBackground(backgroundGetter);
|
|
141
153
|
});
|
|
142
|
-
|
|
154
|
+
if (isNecessaryAddFirstPage(docStructure)) {
|
|
155
|
+
this.writer.addPage(this.pageSize, null, this.pageMargins);
|
|
156
|
+
}
|
|
143
157
|
this.processNode(docStructure);
|
|
144
158
|
this.addHeadersAndFooters(header, footer);
|
|
145
|
-
|
|
146
|
-
this.addWatermark(watermark, pdfDocument, defaultStyle);
|
|
147
|
-
}
|
|
159
|
+
this.addWatermark(watermark, pdfDocument, defaultStyle);
|
|
148
160
|
return {
|
|
149
161
|
pages: this.writer.context().pages,
|
|
150
162
|
linearNodeList: this.linearNodeList
|
|
@@ -157,22 +169,30 @@ class LayoutBuilder {
|
|
|
157
169
|
let pageBackground = backgroundGetter(context.page + 1, pageSize);
|
|
158
170
|
if (pageBackground) {
|
|
159
171
|
this.writer.beginUnbreakableBlock(pageSize.width, pageSize.height);
|
|
160
|
-
pageBackground = this.docPreprocessor.
|
|
161
|
-
this.processNode(this.docMeasure.
|
|
172
|
+
pageBackground = this.docPreprocessor.preprocessBlock(pageBackground);
|
|
173
|
+
this.processNode(this.docMeasure.measureBlock(pageBackground));
|
|
162
174
|
this.writer.commitUnbreakableBlock(0, 0);
|
|
163
175
|
context.backgroundLength[context.page] += pageBackground.positions.length;
|
|
164
176
|
}
|
|
165
177
|
}
|
|
166
|
-
addDynamicRepeatable(nodeGetter, sizeFunction) {
|
|
178
|
+
addDynamicRepeatable(nodeGetter, sizeFunction, customPropertyName) {
|
|
167
179
|
let pages = this.writer.context().pages;
|
|
168
180
|
for (let pageIndex = 0, l = pages.length; pageIndex < l; pageIndex++) {
|
|
169
181
|
this.writer.context().page = pageIndex;
|
|
170
|
-
let
|
|
182
|
+
let customProperties = this.writer.context().getCurrentPage().customProperties;
|
|
183
|
+
let pageNodeGetter = nodeGetter;
|
|
184
|
+
if (customProperties[customPropertyName] || customProperties[customPropertyName] === null) {
|
|
185
|
+
pageNodeGetter = customProperties[customPropertyName];
|
|
186
|
+
}
|
|
187
|
+
if (typeof pageNodeGetter === 'undefined' || pageNodeGetter === null) {
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
190
|
+
let node = pageNodeGetter(pageIndex + 1, l, this.writer.context().pages[pageIndex].pageSize);
|
|
171
191
|
if (node) {
|
|
172
192
|
let sizes = sizeFunction(this.writer.context().getCurrentPage().pageSize, this.writer.context().getCurrentPage().pageMargins);
|
|
173
193
|
this.writer.beginUnbreakableBlock(sizes.width, sizes.height);
|
|
174
|
-
node = this.docPreprocessor.
|
|
175
|
-
this.processNode(this.docMeasure.
|
|
194
|
+
node = this.docPreprocessor.preprocessBlock(node);
|
|
195
|
+
this.processNode(this.docMeasure.measureBlock(node));
|
|
176
196
|
this.writer.commitUnbreakableBlock(sizes.x, sizes.y);
|
|
177
197
|
}
|
|
178
198
|
}
|
|
@@ -190,27 +210,30 @@ class LayoutBuilder {
|
|
|
190
210
|
width: pageSize.width,
|
|
191
211
|
height: pageMargins.bottom
|
|
192
212
|
});
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
}
|
|
196
|
-
if (footer) {
|
|
197
|
-
this.addDynamicRepeatable(footer, footerSizeFct);
|
|
198
|
-
}
|
|
213
|
+
this.addDynamicRepeatable(header, headerSizeFct, 'header');
|
|
214
|
+
this.addDynamicRepeatable(footer, footerSizeFct, 'footer');
|
|
199
215
|
}
|
|
200
216
|
addWatermark(watermark, pdfDocument, defaultStyle) {
|
|
201
|
-
if ((0, _variableType.isString)(watermark)) {
|
|
202
|
-
watermark = {
|
|
203
|
-
'text': watermark
|
|
204
|
-
};
|
|
205
|
-
}
|
|
206
|
-
if (!watermark.text) {
|
|
207
|
-
// empty watermark text
|
|
208
|
-
return;
|
|
209
|
-
}
|
|
210
217
|
let pages = this.writer.context().pages;
|
|
211
218
|
for (let i = 0, l = pages.length; i < l; i++) {
|
|
219
|
+
let pageWatermark = watermark;
|
|
220
|
+
if (pages[i].customProperties['watermark'] || pages[i].customProperties['watermark'] === null) {
|
|
221
|
+
pageWatermark = pages[i].customProperties['watermark'];
|
|
222
|
+
}
|
|
223
|
+
if (pageWatermark === undefined || pageWatermark === null) {
|
|
224
|
+
continue;
|
|
225
|
+
}
|
|
226
|
+
if ((0, _variableType.isString)(pageWatermark)) {
|
|
227
|
+
pageWatermark = {
|
|
228
|
+
'text': pageWatermark
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
if (!pageWatermark.text) {
|
|
232
|
+
// empty watermark text
|
|
233
|
+
continue;
|
|
234
|
+
}
|
|
212
235
|
pages[i].watermark = getWatermarkObject({
|
|
213
|
-
...
|
|
236
|
+
...pageWatermark
|
|
214
237
|
}, pages[i].pageSize, pdfDocument, defaultStyle);
|
|
215
238
|
}
|
|
216
239
|
function getWatermarkObject(watermark, pageSize, pdfDocument, defaultStyle) {
|
|
@@ -391,6 +414,8 @@ class LayoutBuilder {
|
|
|
391
414
|
}
|
|
392
415
|
if (node.stack) {
|
|
393
416
|
this.processVerticalContainer(node);
|
|
417
|
+
} else if (node.section) {
|
|
418
|
+
this.processSection(node);
|
|
394
419
|
} else if (node.columns) {
|
|
395
420
|
this.processColumns(node);
|
|
396
421
|
} else if (node.ul) {
|
|
@@ -435,6 +460,62 @@ class LayoutBuilder {
|
|
|
435
460
|
}, this);
|
|
436
461
|
}
|
|
437
462
|
|
|
463
|
+
// section
|
|
464
|
+
processSection(sectionNode) {
|
|
465
|
+
// TODO: properties
|
|
466
|
+
|
|
467
|
+
let page = this.writer.context().getCurrentPage();
|
|
468
|
+
if (!page || page && page.items.length) {
|
|
469
|
+
// move to new empty page
|
|
470
|
+
// page definition inherit from current page
|
|
471
|
+
if (sectionNode.pageSize === 'inherit') {
|
|
472
|
+
sectionNode.pageSize = page ? {
|
|
473
|
+
width: page.pageSize.width,
|
|
474
|
+
height: page.pageSize.height
|
|
475
|
+
} : undefined;
|
|
476
|
+
}
|
|
477
|
+
if (sectionNode.pageOrientation === 'inherit') {
|
|
478
|
+
sectionNode.pageOrientation = page ? page.pageSize.orientation : undefined;
|
|
479
|
+
}
|
|
480
|
+
if (sectionNode.pageMargins === 'inherit') {
|
|
481
|
+
sectionNode.pageMargins = page ? page.pageMargins : undefined;
|
|
482
|
+
}
|
|
483
|
+
if (sectionNode.header === 'inherit') {
|
|
484
|
+
sectionNode.header = page ? page.customProperties.header : undefined;
|
|
485
|
+
}
|
|
486
|
+
if (sectionNode.footer === 'inherit') {
|
|
487
|
+
sectionNode.footer = page ? page.customProperties.footer : undefined;
|
|
488
|
+
}
|
|
489
|
+
if (sectionNode.background === 'inherit') {
|
|
490
|
+
sectionNode.background = page ? page.customProperties.background : undefined;
|
|
491
|
+
}
|
|
492
|
+
if (sectionNode.watermark === 'inherit') {
|
|
493
|
+
sectionNode.watermark = page ? page.customProperties.watermark : undefined;
|
|
494
|
+
}
|
|
495
|
+
if (sectionNode.header && typeof sectionNode.header !== 'function' && sectionNode.header !== null) {
|
|
496
|
+
sectionNode.header = (0, _tools.convertToDynamicContent)(sectionNode.header);
|
|
497
|
+
}
|
|
498
|
+
if (sectionNode.footer && typeof sectionNode.footer !== 'function' && sectionNode.footer !== null) {
|
|
499
|
+
sectionNode.footer = (0, _tools.convertToDynamicContent)(sectionNode.footer);
|
|
500
|
+
}
|
|
501
|
+
let customProperties = {};
|
|
502
|
+
if (typeof sectionNode.header !== 'undefined') {
|
|
503
|
+
customProperties.header = sectionNode.header;
|
|
504
|
+
}
|
|
505
|
+
if (typeof sectionNode.footer !== 'undefined') {
|
|
506
|
+
customProperties.footer = sectionNode.footer;
|
|
507
|
+
}
|
|
508
|
+
if (typeof sectionNode.background !== 'undefined') {
|
|
509
|
+
customProperties.background = sectionNode.background;
|
|
510
|
+
}
|
|
511
|
+
if (typeof sectionNode.watermark !== 'undefined') {
|
|
512
|
+
customProperties.watermark = sectionNode.watermark;
|
|
513
|
+
}
|
|
514
|
+
this.writer.addPage(sectionNode.pageSize || this.pageSize, sectionNode.pageOrientation, sectionNode.pageMargins || this.pageMargins, customProperties);
|
|
515
|
+
}
|
|
516
|
+
this.processNode(sectionNode.section);
|
|
517
|
+
}
|
|
518
|
+
|
|
438
519
|
// columns
|
|
439
520
|
processColumns(columnNode) {
|
|
440
521
|
this.nestedLevel++;
|
|
@@ -912,6 +993,23 @@ class LayoutBuilder {
|
|
|
912
993
|
}
|
|
913
994
|
return newInline;
|
|
914
995
|
}
|
|
996
|
+
function findMaxFitLength(text, maxWidth, measureFn) {
|
|
997
|
+
let low = 1;
|
|
998
|
+
let high = text.length;
|
|
999
|
+
let bestFit = 1;
|
|
1000
|
+
while (low <= high) {
|
|
1001
|
+
const mid = Math.floor((low + high) / 2);
|
|
1002
|
+
const part = text.substring(0, mid);
|
|
1003
|
+
const width = measureFn(part);
|
|
1004
|
+
if (width <= maxWidth) {
|
|
1005
|
+
bestFit = mid;
|
|
1006
|
+
low = mid + 1;
|
|
1007
|
+
} else {
|
|
1008
|
+
high = mid - 1;
|
|
1009
|
+
}
|
|
1010
|
+
}
|
|
1011
|
+
return bestFit;
|
|
1012
|
+
}
|
|
915
1013
|
if (!textNode._inlines || textNode._inlines.length === 0) {
|
|
916
1014
|
return null;
|
|
917
1015
|
}
|
|
@@ -923,11 +1021,7 @@ class LayoutBuilder {
|
|
|
923
1021
|
let inline = textNode._inlines.shift();
|
|
924
1022
|
isForceContinue = false;
|
|
925
1023
|
if (!inline.noWrap && inline.text.length > 1 && inline.width > line.getAvailableWidth()) {
|
|
926
|
-
let
|
|
927
|
-
let maxChars = Math.floor(line.getAvailableWidth() / widthPerChar);
|
|
928
|
-
if (maxChars < 1) {
|
|
929
|
-
maxChars = 1;
|
|
930
|
-
}
|
|
1024
|
+
let maxChars = findMaxFitLength(inline.text, line.getAvailableWidth(), txt => textInlines.widthOfText(txt, inline));
|
|
931
1025
|
if (maxChars < inline.text.length) {
|
|
932
1026
|
let newInline = cloneInline(inline);
|
|
933
1027
|
newInline.text = inline.text.substr(maxChars);
|
package/js/PageElementWriter.js
CHANGED
|
@@ -73,10 +73,10 @@ class PageElementWriter extends _ElementWriter.default {
|
|
|
73
73
|
y: this.context().y
|
|
74
74
|
});
|
|
75
75
|
}
|
|
76
|
-
addPage(pageSize, pageOrientation, pageMargin) {
|
|
76
|
+
addPage(pageSize, pageOrientation, pageMargin, customProperties = {}) {
|
|
77
77
|
let prevPage = this.page;
|
|
78
78
|
let prevY = this.y;
|
|
79
|
-
this.context().addPage((0, _PageSize.normalizePageSize)(pageSize, pageOrientation), (0, _PageSize.normalizePageMargin)(pageMargin));
|
|
79
|
+
this.context().addPage((0, _PageSize.normalizePageSize)(pageSize, pageOrientation), (0, _PageSize.normalizePageMargin)(pageMargin), customProperties);
|
|
80
80
|
this.emit('pageChanged', {
|
|
81
81
|
prevPage: prevPage,
|
|
82
82
|
prevY: prevY,
|
package/js/Printer.js
CHANGED
|
@@ -103,7 +103,9 @@ class PdfPrinter {
|
|
|
103
103
|
// was laid out using the height of each of the items in the page.
|
|
104
104
|
if (pageSize.height === Infinity) {
|
|
105
105
|
let pageHeight = calculatePageHeight(pages, docDefinition.pageMargins);
|
|
106
|
-
|
|
106
|
+
pages.forEach(page => {
|
|
107
|
+
page.pageSize.height = pageHeight;
|
|
108
|
+
});
|
|
107
109
|
}
|
|
108
110
|
const renderer = new _Renderer.default(this.pdfKitDoc, options.progressCallback);
|
|
109
111
|
renderer.renderPages(pages);
|
package/js/StyleContextStack.js
CHANGED
|
@@ -64,6 +64,10 @@ class StyleContextStack {
|
|
|
64
64
|
if ((0, _variableType.isString)(item)) {
|
|
65
65
|
return 0;
|
|
66
66
|
}
|
|
67
|
+
if (typeof item.section !== 'undefined') {
|
|
68
|
+
// section node not support style overrides
|
|
69
|
+
return 0;
|
|
70
|
+
}
|
|
67
71
|
let styleNames = [];
|
|
68
72
|
if (item.style) {
|
|
69
73
|
if (Array.isArray(item.style)) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pdfmake",
|
|
3
|
-
"version": "0.3.0-beta.
|
|
3
|
+
"version": "0.3.0-beta.18",
|
|
4
4
|
"description": "Client/server side PDF printing in pure JavaScript",
|
|
5
5
|
"main": "js/index.js",
|
|
6
6
|
"esnext": "src/index.js",
|
|
@@ -10,27 +10,27 @@
|
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"linebreak": "^1.1.0",
|
|
13
|
-
"pdfkit": "^0.17.
|
|
14
|
-
"xmldoc": "^2.0.
|
|
13
|
+
"pdfkit": "^0.17.1",
|
|
14
|
+
"xmldoc": "^2.0.1"
|
|
15
15
|
},
|
|
16
16
|
"devDependencies": {
|
|
17
|
-
"@babel/cli": "^7.27.
|
|
18
|
-
"@babel/core": "^7.
|
|
19
|
-
"@babel/plugin-transform-modules-commonjs": "^7.
|
|
20
|
-
"@babel/preset-env": "^7.
|
|
21
|
-
"@eslint/js": "^9.
|
|
17
|
+
"@babel/cli": "^7.27.2",
|
|
18
|
+
"@babel/core": "^7.27.1",
|
|
19
|
+
"@babel/plugin-transform-modules-commonjs": "^7.27.1",
|
|
20
|
+
"@babel/preset-env": "^7.27.2",
|
|
21
|
+
"@eslint/js": "^9.26.0",
|
|
22
22
|
"assert": "^2.1.0",
|
|
23
23
|
"babel-loader": "^10.0.0",
|
|
24
24
|
"brfs": "^2.0.2",
|
|
25
25
|
"browserify-zlib": "^0.2.0",
|
|
26
26
|
"buffer": "^6.0.3",
|
|
27
|
-
"core-js": "^3.
|
|
28
|
-
"eslint": "^9.
|
|
27
|
+
"core-js": "^3.42.0",
|
|
28
|
+
"eslint": "^9.26.0",
|
|
29
29
|
"eslint-plugin-jsdoc": "^50.6.11",
|
|
30
30
|
"expose-loader": "^5.0.1",
|
|
31
31
|
"file-saver": "^2.0.5",
|
|
32
|
-
"globals": "^16.
|
|
33
|
-
"mocha": "^11.
|
|
32
|
+
"globals": "^16.1.0",
|
|
33
|
+
"mocha": "^11.2.2",
|
|
34
34
|
"npm-run-all": "^4.1.5",
|
|
35
35
|
"process": "^0.11.10",
|
|
36
36
|
"rewire": "^7.0.0",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"terser-webpack-plugin": "^5.3.14",
|
|
44
44
|
"transform-loader": "^0.2.4",
|
|
45
45
|
"util": "^0.12.5",
|
|
46
|
-
"webpack": "^5.99.
|
|
46
|
+
"webpack": "^5.99.8",
|
|
47
47
|
"webpack-cli": "^6.0.1"
|
|
48
48
|
},
|
|
49
49
|
"engines": {
|
package/src/DocMeasure.js
CHANGED
|
@@ -34,12 +34,18 @@ class DocMeasure {
|
|
|
34
34
|
return this.measureNode(docStructure);
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
+
measureBlock(node) {
|
|
38
|
+
return this.measureNode(node);
|
|
39
|
+
}
|
|
40
|
+
|
|
37
41
|
measureNode(node) {
|
|
38
42
|
return this.styleStack.auto(node, () => {
|
|
39
43
|
// TODO: refactor + rethink whether this is the proper way to handle margins
|
|
40
44
|
node._margin = getNodeMargin(node, this.styleStack);
|
|
41
45
|
|
|
42
|
-
if (node.
|
|
46
|
+
if (node.section) {
|
|
47
|
+
return extendMargins(this.measureSection(node));
|
|
48
|
+
} else if (node.columns) {
|
|
43
49
|
return extendMargins(this.measureColumns(node));
|
|
44
50
|
} else if (node.stack) {
|
|
45
51
|
return extendMargins(this.measureVerticalContainer(node));
|
|
@@ -465,6 +471,14 @@ class DocMeasure {
|
|
|
465
471
|
return node;
|
|
466
472
|
}
|
|
467
473
|
|
|
474
|
+
measureSection(node) {
|
|
475
|
+
// TODO: properties
|
|
476
|
+
|
|
477
|
+
node.section = this.measureNode(node.section);
|
|
478
|
+
|
|
479
|
+
return node;
|
|
480
|
+
}
|
|
481
|
+
|
|
468
482
|
measureColumns(node) {
|
|
469
483
|
let columns = node.columns;
|
|
470
484
|
node._gap = this.styleStack.getProperty('columnGap') || 0;
|
package/src/DocPreprocessor.js
CHANGED
|
@@ -20,10 +20,17 @@ class DocPreprocessor {
|
|
|
20
20
|
this.parentNode = null;
|
|
21
21
|
this.tocs = [];
|
|
22
22
|
this.nodeReferences = [];
|
|
23
|
-
return this.preprocessNode(docStructure);
|
|
23
|
+
return this.preprocessNode(docStructure, true);
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
preprocessBlock(node) {
|
|
27
|
+
this.parentNode = null;
|
|
28
|
+
this.tocs = [];
|
|
29
|
+
this.nodeReferences = [];
|
|
30
|
+
return this.preprocessNode(node);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
preprocessNode(node, isSectionAllowed = false) {
|
|
27
34
|
// expand shortcuts and casting values
|
|
28
35
|
if (Array.isArray(node)) {
|
|
29
36
|
node = { stack: node };
|
|
@@ -33,10 +40,16 @@ class DocPreprocessor {
|
|
|
33
40
|
node.text = convertValueToString(node.text);
|
|
34
41
|
}
|
|
35
42
|
|
|
36
|
-
if (node.
|
|
43
|
+
if (node.section) {
|
|
44
|
+
if (!isSectionAllowed) {
|
|
45
|
+
throw new Error(`Incorrect document structure, section node is only allowed at the root level of document structure: ${stringifyNode(node)}`);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return this.preprocessSection(node);
|
|
49
|
+
} else if (node.columns) {
|
|
37
50
|
return this.preprocessColumns(node);
|
|
38
51
|
} else if (node.stack) {
|
|
39
|
-
return this.preprocessVerticalContainer(node);
|
|
52
|
+
return this.preprocessVerticalContainer(node, isSectionAllowed);
|
|
40
53
|
} else if (node.ul) {
|
|
41
54
|
return this.preprocessList(node);
|
|
42
55
|
} else if (node.ol) {
|
|
@@ -64,6 +77,12 @@ class DocPreprocessor {
|
|
|
64
77
|
}
|
|
65
78
|
}
|
|
66
79
|
|
|
80
|
+
preprocessSection(node) {
|
|
81
|
+
node.section = this.preprocessNode(node.section);
|
|
82
|
+
|
|
83
|
+
return node;
|
|
84
|
+
}
|
|
85
|
+
|
|
67
86
|
preprocessColumns(node) {
|
|
68
87
|
let columns = node.columns;
|
|
69
88
|
|
|
@@ -74,11 +93,11 @@ class DocPreprocessor {
|
|
|
74
93
|
return node;
|
|
75
94
|
}
|
|
76
95
|
|
|
77
|
-
preprocessVerticalContainer(node) {
|
|
96
|
+
preprocessVerticalContainer(node, isSectionAllowed) {
|
|
78
97
|
let items = node.stack;
|
|
79
98
|
|
|
80
99
|
for (let i = 0, l = items.length; i < l; i++) {
|
|
81
|
-
items[i] = this.preprocessNode(items[i]);
|
|
100
|
+
items[i] = this.preprocessNode(items[i], isSectionAllowed);
|
|
82
101
|
}
|
|
83
102
|
|
|
84
103
|
return node;
|
package/src/DocumentContext.js
CHANGED
|
@@ -222,7 +222,7 @@ class DocumentContext extends EventEmitter {
|
|
|
222
222
|
let currentPageOrientation = this.getCurrentPage().pageSize.orientation;
|
|
223
223
|
|
|
224
224
|
let pageSize = getPageSize(this.getCurrentPage(), pageOrientation);
|
|
225
|
-
this.addPage(pageSize);
|
|
225
|
+
this.addPage(pageSize, null, this.getCurrentPage().customProperties);
|
|
226
226
|
|
|
227
227
|
if (currentPageOrientation === pageSize.orientation) {
|
|
228
228
|
this.availableWidth = currentAvailableWidth;
|
|
@@ -240,20 +240,20 @@ class DocumentContext extends EventEmitter {
|
|
|
240
240
|
};
|
|
241
241
|
}
|
|
242
242
|
|
|
243
|
-
addPage(pageSize, pageMargin = null) {
|
|
243
|
+
addPage(pageSize, pageMargin = null, customProperties = {}) {
|
|
244
244
|
if (pageMargin !== null) {
|
|
245
245
|
this.pageMargins = pageMargin;
|
|
246
246
|
this.x = pageMargin.left;
|
|
247
247
|
this.availableWidth = pageSize.width - pageMargin.left - pageMargin.right;
|
|
248
248
|
}
|
|
249
249
|
|
|
250
|
-
let page = { items: [], pageSize: pageSize, pageMargins: this.pageMargins };
|
|
250
|
+
let page = { items: [], pageSize: pageSize, pageMargins: this.pageMargins, customProperties: customProperties };
|
|
251
251
|
this.pages.push(page);
|
|
252
252
|
this.backgroundLength.push(0);
|
|
253
253
|
this.page = this.pages.length - 1;
|
|
254
254
|
this.initializePage();
|
|
255
255
|
|
|
256
|
-
this.emit('pageAdded');
|
|
256
|
+
this.emit('pageAdded', page);
|
|
257
257
|
|
|
258
258
|
return page;
|
|
259
259
|
}
|