pdfmake 0.2.4 → 0.3.0-beta.2

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.
Files changed (128) hide show
  1. package/CHANGELOG.md +10 -27
  2. package/README.md +11 -7
  3. package/build/pdfmake.js +44733 -42435
  4. package/build/pdfmake.js.map +1 -1
  5. package/build/pdfmake.min.js +2 -2
  6. package/build/pdfmake.min.js.map +1 -1
  7. package/build/standard-fonts/Courier.js +27 -0
  8. package/build/standard-fonts/Helvetica.js +27 -0
  9. package/build/standard-fonts/Symbol.js +21 -0
  10. package/build/standard-fonts/Times.js +27 -0
  11. package/build/standard-fonts/ZapfDingbats.js +21 -0
  12. package/build/vfs_fonts.js +2 -2
  13. package/build-vfs.js +2 -2
  14. package/fonts/Roboto/Roboto-Italic.ttf +0 -0
  15. package/fonts/Roboto/Roboto-Medium.ttf +0 -0
  16. package/fonts/Roboto/Roboto-MediumItalic.ttf +0 -0
  17. package/fonts/Roboto/Roboto-Regular.ttf +0 -0
  18. package/fonts/Roboto.js +8 -0
  19. package/js/3rd-party/svg-to-pdfkit/source.js +4301 -0
  20. package/js/3rd-party/svg-to-pdfkit.js +11 -0
  21. package/js/DocMeasure.js +758 -0
  22. package/js/DocPreprocessor.js +291 -0
  23. package/js/DocumentContext.js +306 -0
  24. package/js/ElementWriter.js +400 -0
  25. package/js/LayoutBuilder.js +840 -0
  26. package/js/Line.js +125 -0
  27. package/js/OutputDocument.js +86 -0
  28. package/js/OutputDocumentServer.js +34 -0
  29. package/js/PDFDocument.js +190 -0
  30. package/js/PageElementWriter.js +165 -0
  31. package/js/PageSize.js +88 -0
  32. package/js/Printer.js +300 -0
  33. package/js/Renderer.js +463 -0
  34. package/js/SVGMeasure.js +89 -0
  35. package/js/StyleContextStack.js +206 -0
  36. package/js/TableProcessor.js +590 -0
  37. package/js/TextBreaker.js +182 -0
  38. package/js/TextDecorator.js +181 -0
  39. package/js/TextInlines.js +248 -0
  40. package/js/URLResolver.js +82 -0
  41. package/js/base.js +69 -0
  42. package/js/browser-extensions/OutputDocumentBrowser.js +131 -0
  43. package/js/browser-extensions/URLBrowserResolver.js +94 -0
  44. package/js/browser-extensions/fonts/Roboto.js +42 -0
  45. package/js/browser-extensions/index.js +70 -0
  46. package/js/browser-extensions/pdfMake.js +17 -0
  47. package/js/browser-extensions/standard-fonts/Courier.js +42 -0
  48. package/js/browser-extensions/standard-fonts/Helvetica.js +42 -0
  49. package/js/browser-extensions/standard-fonts/Symbol.js +27 -0
  50. package/js/browser-extensions/standard-fonts/Times.js +42 -0
  51. package/js/browser-extensions/standard-fonts/ZapfDingbats.js +27 -0
  52. package/js/browser-extensions/virtual-fs-cjs.js +3 -0
  53. package/js/columnCalculator.js +142 -0
  54. package/js/helpers/node.js +122 -0
  55. package/js/helpers/tools.js +48 -0
  56. package/js/helpers/variableType.js +52 -0
  57. package/js/index.js +21 -0
  58. package/js/qrEnc.js +810 -0
  59. package/js/standardPageSizes.js +57 -0
  60. package/js/tableLayouts.js +127 -0
  61. package/js/virtual-fs.js +77 -0
  62. package/package.json +26 -22
  63. package/src/3rd-party/svg-to-pdfkit.js +2 -2
  64. package/src/DocMeasure.js +703 -0
  65. package/src/DocPreprocessor.js +264 -0
  66. package/src/DocumentContext.js +309 -0
  67. package/src/ElementWriter.js +394 -0
  68. package/src/LayoutBuilder.js +821 -0
  69. package/src/Line.js +114 -0
  70. package/src/OutputDocument.js +78 -0
  71. package/src/OutputDocumentServer.js +26 -0
  72. package/src/PDFDocument.js +174 -0
  73. package/src/PageElementWriter.js +160 -0
  74. package/src/PageSize.js +53 -0
  75. package/src/Printer.js +277 -0
  76. package/src/Renderer.js +405 -0
  77. package/src/SVGMeasure.js +79 -0
  78. package/src/StyleContextStack.js +216 -0
  79. package/src/TableProcessor.js +558 -0
  80. package/src/TextBreaker.js +149 -0
  81. package/src/TextDecorator.js +161 -0
  82. package/src/TextInlines.js +223 -0
  83. package/src/URLResolver.js +72 -0
  84. package/src/base.js +61 -0
  85. package/src/browser-extensions/OutputDocumentBrowser.js +117 -0
  86. package/src/browser-extensions/URLBrowserResolver.js +49 -53
  87. package/src/browser-extensions/fonts/Roboto.js +27 -0
  88. package/src/browser-extensions/index.js +55 -0
  89. package/src/browser-extensions/pdfMake.js +10 -282
  90. package/src/browser-extensions/standard-fonts/Courier.js +27 -0
  91. package/src/browser-extensions/standard-fonts/Helvetica.js +27 -0
  92. package/src/browser-extensions/standard-fonts/Symbol.js +21 -0
  93. package/src/browser-extensions/standard-fonts/Times.js +27 -0
  94. package/src/browser-extensions/standard-fonts/ZapfDingbats.js +21 -0
  95. package/src/browser-extensions/virtual-fs-cjs.js +1 -0
  96. package/src/columnCalculator.js +29 -32
  97. package/src/helpers/node.js +110 -0
  98. package/src/helpers/tools.js +39 -0
  99. package/src/helpers/variableType.js +39 -0
  100. package/src/index.js +16 -0
  101. package/src/qrEnc.js +15 -10
  102. package/src/standardPageSizes.js +1 -3
  103. package/src/tableLayouts.js +100 -0
  104. package/src/virtual-fs.js +66 -0
  105. package/standard-fonts/Courier.js +8 -0
  106. package/standard-fonts/Helvetica.js +9 -0
  107. package/standard-fonts/Symbol.js +5 -0
  108. package/standard-fonts/Times.js +8 -0
  109. package/standard-fonts/ZapfDingbats.js +5 -0
  110. package/src/browser-extensions/virtual-fs.js +0 -55
  111. package/src/docMeasure.js +0 -807
  112. package/src/docPreprocessor.js +0 -255
  113. package/src/documentContext.js +0 -314
  114. package/src/elementWriter.js +0 -322
  115. package/src/fontProvider.js +0 -68
  116. package/src/helpers.js +0 -126
  117. package/src/imageMeasure.js +0 -51
  118. package/src/layoutBuilder.js +0 -807
  119. package/src/line.js +0 -91
  120. package/src/pageElementWriter.js +0 -174
  121. package/src/pdfKitEngine.js +0 -21
  122. package/src/printer.js +0 -705
  123. package/src/styleContextStack.js +0 -179
  124. package/src/svgMeasure.js +0 -70
  125. package/src/tableProcessor.js +0 -561
  126. package/src/textDecorator.js +0 -157
  127. package/src/textTools.js +0 -373
  128. package/src/traversalTracker.js +0 -47
@@ -0,0 +1,840 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.default = void 0;
5
+
6
+ var _DocPreprocessor = _interopRequireDefault(require("./DocPreprocessor"));
7
+
8
+ var _DocMeasure = _interopRequireDefault(require("./DocMeasure"));
9
+
10
+ var _DocumentContext = _interopRequireDefault(require("./DocumentContext"));
11
+
12
+ var _PageElementWriter = _interopRequireDefault(require("./PageElementWriter"));
13
+
14
+ var _columnCalculator = _interopRequireDefault(require("./columnCalculator"));
15
+
16
+ var _TableProcessor = _interopRequireDefault(require("./TableProcessor"));
17
+
18
+ var _Line = _interopRequireDefault(require("./Line"));
19
+
20
+ var _variableType = require("./helpers/variableType");
21
+
22
+ var _node = require("./helpers/node");
23
+
24
+ var _tools = require("./helpers/tools");
25
+
26
+ var _TextInlines = _interopRequireDefault(require("./TextInlines"));
27
+
28
+ var _StyleContextStack = _interopRequireDefault(require("./StyleContextStack"));
29
+
30
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
31
+
32
+ function addAll(target, otherArray) {
33
+ otherArray.forEach(item => {
34
+ target.push(item);
35
+ });
36
+ }
37
+ /**
38
+ * Layout engine which turns document-definition-object into a set of pages, lines, inlines
39
+ * and vectors ready to be rendered into a PDF
40
+ */
41
+
42
+
43
+ class LayoutBuilder {
44
+ /**
45
+ * @param {object} pageSize - an object defining page width and height
46
+ * @param {object} pageMargins - an object defining top, left, right and bottom margins
47
+ * @param {object} svgMeasure
48
+ */
49
+ constructor(pageSize, pageMargins, svgMeasure) {
50
+ this.pageSize = pageSize;
51
+ this.pageMargins = pageMargins;
52
+ this.svgMeasure = svgMeasure;
53
+ this.tableLayouts = {};
54
+ }
55
+
56
+ registerTableLayouts(tableLayouts) {
57
+ this.tableLayouts = (0, _tools.pack)(this.tableLayouts, tableLayouts);
58
+ }
59
+ /**
60
+ * Executes layout engine on document-definition-object and creates an array of pages
61
+ * containing positioned Blocks, Lines and inlines
62
+ *
63
+ * @param {object} docStructure document-definition-object
64
+ * @param {object} pdfDocument pdfkit document
65
+ * @param {object} styleDictionary dictionary with style definitions
66
+ * @param {object} defaultStyle default style definition
67
+ * @param {object} background
68
+ * @param {object} header
69
+ * @param {object} footer
70
+ * @param {object} watermark
71
+ * @param {object} pageBreakBeforeFct
72
+ * @returns {Array} an array of pages
73
+ */
74
+
75
+
76
+ layoutDocument(docStructure, pdfDocument, styleDictionary, defaultStyle, background, header, footer, watermark, pageBreakBeforeFct) {
77
+ function addPageBreaksIfNecessary(linearNodeList, pages) {
78
+ if (typeof pageBreakBeforeFct !== 'function') {
79
+ return false;
80
+ }
81
+
82
+ linearNodeList = linearNodeList.filter(node => node.positions.length > 0);
83
+ linearNodeList.forEach(node => {
84
+ let nodeInfo = {};
85
+ ['id', 'text', 'ul', 'ol', 'table', 'image', 'qr', 'canvas', 'svg', 'columns', 'headlineLevel', 'style', 'pageBreak', 'pageOrientation', 'width', 'height'].forEach(key => {
86
+ if (node[key] !== undefined) {
87
+ nodeInfo[key] = node[key];
88
+ }
89
+ });
90
+ nodeInfo.startPosition = node.positions[0];
91
+ nodeInfo.pageNumbers = Array.from(new Set(node.positions.map(node => node.pageNumber)));
92
+ nodeInfo.pages = pages.length;
93
+ nodeInfo.stack = Array.isArray(node.stack);
94
+ node.nodeInfo = nodeInfo;
95
+ });
96
+
97
+ for (let index = 0; index < linearNodeList.length; index++) {
98
+ let node = linearNodeList[index];
99
+
100
+ if (node.pageBreak !== 'before' && !node.pageBreakCalculated) {
101
+ node.pageBreakCalculated = true;
102
+ let pageNumber = node.nodeInfo.pageNumbers[0];
103
+
104
+ if (pageBreakBeforeFct(node.nodeInfo, {
105
+ getFollowingNodesOnPage: () => {
106
+ let followingNodesOnPage = [];
107
+
108
+ for (let ii = index + 1, l = linearNodeList.length; ii < l; ii++) {
109
+ if (linearNodeList[ii].nodeInfo.pageNumbers.indexOf(pageNumber) > -1) {
110
+ followingNodesOnPage.push(linearNodeList[ii].nodeInfo);
111
+ }
112
+ }
113
+
114
+ return followingNodesOnPage;
115
+ },
116
+ getNodesOnNextPage: () => {
117
+ let nodesOnNextPage = [];
118
+
119
+ for (let ii = index + 1, l = linearNodeList.length; ii < l; ii++) {
120
+ if (linearNodeList[ii].nodeInfo.pageNumbers.indexOf(pageNumber + 1) > -1) {
121
+ nodesOnNextPage.push(linearNodeList[ii].nodeInfo);
122
+ }
123
+ }
124
+
125
+ return nodesOnNextPage;
126
+ },
127
+ getPreviousNodesOnPage: () => {
128
+ let previousNodesOnPage = [];
129
+
130
+ for (let ii = 0; ii < index; ii++) {
131
+ if (linearNodeList[ii].nodeInfo.pageNumbers.indexOf(pageNumber) > -1) {
132
+ previousNodesOnPage.push(linearNodeList[ii].nodeInfo);
133
+ }
134
+ }
135
+
136
+ return previousNodesOnPage;
137
+ }
138
+ })) {
139
+ node.pageBreak = 'before';
140
+ return true;
141
+ }
142
+ }
143
+ }
144
+
145
+ return false;
146
+ }
147
+
148
+ this.docPreprocessor = new _DocPreprocessor.default();
149
+ this.docMeasure = new _DocMeasure.default(pdfDocument, styleDictionary, defaultStyle, this.svgMeasure, this.tableLayouts);
150
+
151
+ function resetXYs(result) {
152
+ result.linearNodeList.forEach(node => {
153
+ node.resetXY();
154
+ });
155
+ }
156
+
157
+ let result = this.tryLayoutDocument(docStructure, pdfDocument, styleDictionary, defaultStyle, background, header, footer, watermark);
158
+
159
+ while (addPageBreaksIfNecessary(result.linearNodeList, result.pages)) {
160
+ resetXYs(result);
161
+ result = this.tryLayoutDocument(docStructure, pdfDocument, styleDictionary, defaultStyle, background, header, footer, watermark);
162
+ }
163
+
164
+ return result.pages;
165
+ }
166
+
167
+ tryLayoutDocument(docStructure, pdfDocument, styleDictionary, defaultStyle, background, header, footer, watermark) {
168
+ this.linearNodeList = [];
169
+ docStructure = this.docPreprocessor.preprocessDocument(docStructure);
170
+ docStructure = this.docMeasure.measureDocument(docStructure);
171
+ this.writer = new _PageElementWriter.default(new _DocumentContext.default(this.pageSize, this.pageMargins));
172
+ this.writer.context().addListener('pageAdded', () => {
173
+ this.addBackground(background);
174
+ });
175
+ this.addBackground(background);
176
+ this.processNode(docStructure);
177
+ this.addHeadersAndFooters(header, footer);
178
+
179
+ if (watermark != null) {
180
+ this.addWatermark(watermark, pdfDocument, defaultStyle);
181
+ }
182
+
183
+ return {
184
+ pages: this.writer.context().pages,
185
+ linearNodeList: this.linearNodeList
186
+ };
187
+ }
188
+
189
+ addBackground(background) {
190
+ let backgroundGetter = typeof background === 'function' ? background : () => background;
191
+ let context = this.writer.context();
192
+ let pageSize = context.getCurrentPage().pageSize;
193
+ let pageBackground = backgroundGetter(context.page + 1, pageSize);
194
+
195
+ if (pageBackground) {
196
+ this.writer.beginUnbreakableBlock(pageSize.width, pageSize.height);
197
+ pageBackground = this.docPreprocessor.preprocessDocument(pageBackground);
198
+ this.processNode(this.docMeasure.measureDocument(pageBackground));
199
+ this.writer.commitUnbreakableBlock(0, 0);
200
+ context.backgroundLength[context.page] += pageBackground.positions.length;
201
+ }
202
+ }
203
+
204
+ addStaticRepeatable(headerOrFooter, sizeFunction) {
205
+ this.addDynamicRepeatable(() => // copy to new object
206
+ JSON.parse(JSON.stringify(headerOrFooter)), sizeFunction);
207
+ }
208
+
209
+ addDynamicRepeatable(nodeGetter, sizeFunction) {
210
+ let pages = this.writer.context().pages;
211
+
212
+ for (let pageIndex = 0, l = pages.length; pageIndex < l; pageIndex++) {
213
+ this.writer.context().page = pageIndex;
214
+ let node = nodeGetter(pageIndex + 1, l, this.writer.context().pages[pageIndex].pageSize);
215
+
216
+ if (node) {
217
+ let sizes = sizeFunction(this.writer.context().getCurrentPage().pageSize, this.pageMargins);
218
+ this.writer.beginUnbreakableBlock(sizes.width, sizes.height);
219
+ node = this.docPreprocessor.preprocessDocument(node);
220
+ this.processNode(this.docMeasure.measureDocument(node));
221
+ this.writer.commitUnbreakableBlock(sizes.x, sizes.y);
222
+ }
223
+ }
224
+ }
225
+
226
+ addHeadersAndFooters(header, footer) {
227
+ const headerSizeFct = (pageSize, pageMargins) => ({
228
+ x: 0,
229
+ y: 0,
230
+ width: pageSize.width,
231
+ height: pageMargins.top
232
+ });
233
+
234
+ const footerSizeFct = (pageSize, pageMargins) => ({
235
+ x: 0,
236
+ y: pageSize.height - pageMargins.bottom,
237
+ width: pageSize.width,
238
+ height: pageMargins.bottom
239
+ });
240
+
241
+ if (typeof header === 'function') {
242
+ this.addDynamicRepeatable(header, headerSizeFct);
243
+ } else if (header) {
244
+ this.addStaticRepeatable(header, headerSizeFct);
245
+ }
246
+
247
+ if (typeof footer === 'function') {
248
+ this.addDynamicRepeatable(footer, footerSizeFct);
249
+ } else if (footer) {
250
+ this.addStaticRepeatable(footer, footerSizeFct);
251
+ }
252
+ }
253
+
254
+ addWatermark(watermark, pdfDocument, defaultStyle) {
255
+ if ((0, _variableType.isString)(watermark)) {
256
+ watermark = {
257
+ 'text': watermark
258
+ };
259
+ }
260
+
261
+ if (!watermark.text) {
262
+ // empty watermark text
263
+ return;
264
+ }
265
+
266
+ watermark.font = watermark.font || defaultStyle.font || 'Roboto';
267
+ watermark.fontSize = watermark.fontSize || 'auto';
268
+ watermark.color = watermark.color || 'black';
269
+ watermark.opacity = (0, _variableType.isNumber)(watermark.opacity) ? watermark.opacity : 0.6;
270
+ watermark.bold = watermark.bold || false;
271
+ watermark.italics = watermark.italics || false;
272
+ watermark.angle = (0, _variableType.isValue)(watermark.angle) ? watermark.angle : null;
273
+
274
+ if (watermark.angle === null) {
275
+ watermark.angle = Math.atan2(this.pageSize.height, this.pageSize.width) * -180 / Math.PI;
276
+ }
277
+
278
+ if (watermark.fontSize === 'auto') {
279
+ watermark.fontSize = getWatermarkFontSize(this.pageSize, watermark, pdfDocument);
280
+ }
281
+
282
+ let watermarkObject = {
283
+ text: watermark.text,
284
+ font: pdfDocument.provideFont(watermark.font, watermark.bold, watermark.italics),
285
+ fontSize: watermark.fontSize,
286
+ color: watermark.color,
287
+ opacity: watermark.opacity,
288
+ angle: watermark.angle
289
+ };
290
+ watermarkObject._size = getWatermarkSize(watermark, pdfDocument);
291
+ let pages = this.writer.context().pages;
292
+
293
+ for (let i = 0, l = pages.length; i < l; i++) {
294
+ pages[i].watermark = watermarkObject;
295
+ }
296
+
297
+ function getWatermarkSize(watermark, pdfDocument) {
298
+ let textInlines = new _TextInlines.default(pdfDocument);
299
+ let styleContextStack = new _StyleContextStack.default(null, {
300
+ font: watermark.font,
301
+ bold: watermark.bold,
302
+ italics: watermark.italics
303
+ });
304
+ styleContextStack.push({
305
+ fontSize: watermark.fontSize
306
+ });
307
+ let size = textInlines.sizeOfText(watermark.text, styleContextStack);
308
+ let rotatedSize = textInlines.sizeOfRotatedText(watermark.text, watermark.angle, styleContextStack);
309
+ return {
310
+ size: size,
311
+ rotatedSize: rotatedSize
312
+ };
313
+ }
314
+
315
+ function getWatermarkFontSize(pageSize, watermark, pdfDocument) {
316
+ let textInlines = new _TextInlines.default(pdfDocument);
317
+ let styleContextStack = new _StyleContextStack.default(null, {
318
+ font: watermark.font,
319
+ bold: watermark.bold,
320
+ italics: watermark.italics
321
+ });
322
+ let rotatedSize;
323
+ /**
324
+ * Binary search the best font size.
325
+ * Initial bounds [0, 1000]
326
+ * Break when range < 1
327
+ */
328
+
329
+ let a = 0;
330
+ let b = 1000;
331
+ let c = (a + b) / 2;
332
+
333
+ while (Math.abs(a - b) > 1) {
334
+ styleContextStack.push({
335
+ fontSize: c
336
+ });
337
+ rotatedSize = textInlines.sizeOfRotatedText(watermark.text, watermark.angle, styleContextStack);
338
+
339
+ if (rotatedSize.width > pageSize.width) {
340
+ b = c;
341
+ c = (a + b) / 2;
342
+ } else if (rotatedSize.width < pageSize.width) {
343
+ if (rotatedSize.height > pageSize.height) {
344
+ b = c;
345
+ c = (a + b) / 2;
346
+ } else {
347
+ a = c;
348
+ c = (a + b) / 2;
349
+ }
350
+ }
351
+
352
+ styleContextStack.pop();
353
+ }
354
+ /*
355
+ End binary search
356
+ */
357
+
358
+
359
+ return c;
360
+ }
361
+ }
362
+
363
+ processNode(node) {
364
+ const applyMargins = callback => {
365
+ let margin = node._margin;
366
+
367
+ if (node.pageBreak === 'before') {
368
+ this.writer.moveToNextPage(node.pageOrientation);
369
+ } else if (node.pageBreak === 'beforeOdd') {
370
+ this.writer.moveToNextPage(node.pageOrientation);
371
+
372
+ if ((this.writer.context().page + 1) % 2 === 1) {
373
+ this.writer.moveToNextPage(node.pageOrientation);
374
+ }
375
+ } else if (node.pageBreak === 'beforeEven') {
376
+ this.writer.moveToNextPage(node.pageOrientation);
377
+
378
+ if ((this.writer.context().page + 1) % 2 === 0) {
379
+ this.writer.moveToNextPage(node.pageOrientation);
380
+ }
381
+ }
382
+
383
+ if (margin) {
384
+ this.writer.context().moveDown(margin[1]);
385
+ this.writer.context().addMargin(margin[0], margin[2]);
386
+ }
387
+
388
+ callback();
389
+
390
+ if (margin) {
391
+ this.writer.context().addMargin(-margin[0], -margin[2]);
392
+ this.writer.context().moveDown(margin[3]);
393
+ }
394
+
395
+ if (node.pageBreak === 'after') {
396
+ this.writer.moveToNextPage(node.pageOrientation);
397
+ } else if (node.pageBreak === 'afterOdd') {
398
+ this.writer.moveToNextPage(node.pageOrientation);
399
+
400
+ if ((this.writer.context().page + 1) % 2 === 1) {
401
+ this.writer.moveToNextPage(node.pageOrientation);
402
+ }
403
+ } else if (node.pageBreak === 'afterEven') {
404
+ this.writer.moveToNextPage(node.pageOrientation);
405
+
406
+ if ((this.writer.context().page + 1) % 2 === 0) {
407
+ this.writer.moveToNextPage(node.pageOrientation);
408
+ }
409
+ }
410
+ };
411
+
412
+ this.linearNodeList.push(node);
413
+ decorateNode(node);
414
+ applyMargins(() => {
415
+ let unbreakable = node.unbreakable;
416
+
417
+ if (unbreakable) {
418
+ this.writer.beginUnbreakableBlock();
419
+ }
420
+
421
+ let absPosition = node.absolutePosition;
422
+
423
+ if (absPosition) {
424
+ this.writer.context().beginDetachedBlock();
425
+ this.writer.context().moveTo(absPosition.x || 0, absPosition.y || 0);
426
+ }
427
+
428
+ let relPosition = node.relativePosition;
429
+
430
+ if (relPosition) {
431
+ this.writer.context().beginDetachedBlock();
432
+ this.writer.context().moveToRelative(relPosition.x || 0, relPosition.y || 0);
433
+ }
434
+
435
+ if (node.stack) {
436
+ this.processVerticalContainer(node);
437
+ } else if (node.columns) {
438
+ this.processColumns(node);
439
+ } else if (node.ul) {
440
+ this.processList(false, node);
441
+ } else if (node.ol) {
442
+ this.processList(true, node);
443
+ } else if (node.table) {
444
+ this.processTable(node);
445
+ } else if (node.text !== undefined) {
446
+ this.processLeaf(node);
447
+ } else if (node.toc) {
448
+ this.processToc(node);
449
+ } else if (node.image) {
450
+ this.processImage(node);
451
+ } else if (node.svg) {
452
+ this.processSVG(node);
453
+ } else if (node.canvas) {
454
+ this.processCanvas(node);
455
+ } else if (node.qr) {
456
+ this.processQr(node);
457
+ } else if (node.attachment) {
458
+ this.processAttachment(node);
459
+ } else if (!node._span) {
460
+ throw new Error(`Unrecognized document structure: ${(0, _node.stringifyNode)(node)}`);
461
+ }
462
+
463
+ if (absPosition || relPosition) {
464
+ this.writer.context().endDetachedBlock();
465
+ }
466
+
467
+ if (unbreakable) {
468
+ this.writer.commitUnbreakableBlock();
469
+ }
470
+ });
471
+ } // vertical container
472
+
473
+
474
+ processVerticalContainer(node) {
475
+ node.stack.forEach(item => {
476
+ this.processNode(item);
477
+ addAll(node.positions, item.positions); //TODO: paragraph gap
478
+ }, this);
479
+ } // columns
480
+
481
+
482
+ processColumns(columnNode) {
483
+ let columns = columnNode.columns;
484
+ let availableWidth = this.writer.context().availableWidth;
485
+ let gaps = gapArray(columnNode._gap);
486
+
487
+ if (gaps) {
488
+ availableWidth -= (gaps.length - 1) * columnNode._gap;
489
+ }
490
+
491
+ _columnCalculator.default.buildColumnWidths(columns, availableWidth);
492
+
493
+ let result = this.processRow(columns, columns, gaps);
494
+ addAll(columnNode.positions, result.positions);
495
+
496
+ function gapArray(gap) {
497
+ if (!gap) {
498
+ return null;
499
+ }
500
+
501
+ let gaps = [];
502
+ gaps.push(0);
503
+
504
+ for (let i = columns.length - 1; i > 0; i--) {
505
+ gaps.push(gap);
506
+ }
507
+
508
+ return gaps;
509
+ }
510
+ }
511
+
512
+ processRow(columns, widths, gaps, tableBody, tableRow, height) {
513
+ const storePageBreakData = data => {
514
+ let pageDesc;
515
+
516
+ for (let i = 0, l = pageBreaks.length; i < l; i++) {
517
+ let desc = pageBreaks[i];
518
+
519
+ if (desc.prevPage === data.prevPage) {
520
+ pageDesc = desc;
521
+ break;
522
+ }
523
+ }
524
+
525
+ if (!pageDesc) {
526
+ pageDesc = data;
527
+ pageBreaks.push(pageDesc);
528
+ }
529
+
530
+ pageDesc.prevY = Math.max(pageDesc.prevY, data.prevY);
531
+ pageDesc.y = Math.min(pageDesc.y, data.y);
532
+ };
533
+
534
+ let pageBreaks = [];
535
+ let positions = [];
536
+ this.writer.addListener('pageChanged', storePageBreakData);
537
+ widths = widths || columns;
538
+ this.writer.context().beginColumnGroup();
539
+
540
+ for (let i = 0, l = columns.length; i < l; i++) {
541
+ let column = columns[i];
542
+ let width = widths[i]._calcWidth;
543
+ let leftOffset = colLeftOffset(i);
544
+
545
+ if (column.colSpan && column.colSpan > 1) {
546
+ for (let j = 1; j < column.colSpan; j++) {
547
+ width += widths[++i]._calcWidth + gaps[i];
548
+ }
549
+ }
550
+
551
+ this.writer.context().beginColumn(width, leftOffset, getEndingCell(column, i));
552
+
553
+ if (!column._span) {
554
+ this.processNode(column);
555
+ addAll(positions, column.positions);
556
+ } else if (column._columnEndingContext) {
557
+ // row-span ending
558
+ this.writer.context().markEnding(column);
559
+ }
560
+ }
561
+
562
+ this.writer.context().completeColumnGroup(height);
563
+ this.writer.removeListener('pageChanged', storePageBreakData);
564
+ return {
565
+ pageBreaks: pageBreaks,
566
+ positions: positions
567
+ };
568
+
569
+ function colLeftOffset(i) {
570
+ if (gaps && gaps.length > i) {
571
+ return gaps[i];
572
+ }
573
+
574
+ return 0;
575
+ }
576
+
577
+ function getEndingCell(column, columnIndex) {
578
+ if (column.rowSpan && column.rowSpan > 1) {
579
+ let endingRow = tableRow + column.rowSpan - 1;
580
+
581
+ if (endingRow >= tableBody.length) {
582
+ throw new Error(`Row span for column ${columnIndex} (with indexes starting from 0) exceeded row count`);
583
+ }
584
+
585
+ return tableBody[endingRow][columnIndex];
586
+ }
587
+
588
+ return null;
589
+ }
590
+ } // lists
591
+
592
+
593
+ processList(orderedList, node) {
594
+ const addMarkerToFirstLeaf = line => {
595
+ // I'm not very happy with the way list processing is implemented
596
+ // (both code and algorithm should be rethinked)
597
+ if (nextMarker) {
598
+ let marker = nextMarker;
599
+ nextMarker = null;
600
+
601
+ if (marker.canvas) {
602
+ let vector = marker.canvas[0];
603
+ (0, _tools.offsetVector)(vector, -marker._minWidth, 0);
604
+ this.writer.addVector(vector);
605
+ } else if (marker._inlines) {
606
+ let markerLine = new _Line.default(this.pageSize.width);
607
+ markerLine.addInline(marker._inlines[0]);
608
+ markerLine.x = -marker._minWidth;
609
+ markerLine.y = line.getAscenderHeight() - markerLine.getAscenderHeight();
610
+ this.writer.addLine(markerLine, true);
611
+ }
612
+ }
613
+ };
614
+
615
+ let items = orderedList ? node.ol : node.ul;
616
+ let gapSize = node._gapSize;
617
+ this.writer.context().addMargin(gapSize.width);
618
+ let nextMarker;
619
+ this.writer.addListener('lineAdded', addMarkerToFirstLeaf);
620
+ items.forEach(item => {
621
+ nextMarker = item.listMarker;
622
+ this.processNode(item);
623
+ addAll(node.positions, item.positions);
624
+ });
625
+ this.writer.removeListener('lineAdded', addMarkerToFirstLeaf);
626
+ this.writer.context().addMargin(-gapSize.width);
627
+ } // tables
628
+
629
+
630
+ processTable(tableNode) {
631
+ let processor = new _TableProcessor.default(tableNode);
632
+ processor.beginTable(this.writer);
633
+ let rowHeights = tableNode.table.heights;
634
+
635
+ for (let i = 0, l = tableNode.table.body.length; i < l; i++) {
636
+ processor.beginRow(i, this.writer);
637
+ let height;
638
+
639
+ if (typeof rowHeights === 'function') {
640
+ height = rowHeights(i);
641
+ } else if (Array.isArray(rowHeights)) {
642
+ height = rowHeights[i];
643
+ } else {
644
+ height = rowHeights;
645
+ }
646
+
647
+ if (height === 'auto') {
648
+ height = undefined;
649
+ }
650
+
651
+ let result = this.processRow(tableNode.table.body[i], tableNode.table.widths, tableNode._offsets.offsets, tableNode.table.body, i, height);
652
+ addAll(tableNode.positions, result.positions);
653
+ processor.endRow(i, this.writer, result.pageBreaks);
654
+ }
655
+
656
+ processor.endTable(this.writer);
657
+ } // leafs (texts)
658
+
659
+
660
+ processLeaf(node) {
661
+ let line = this.buildNextLine(node);
662
+
663
+ if (line && (node.tocItem || node.id)) {
664
+ line._node = node;
665
+ }
666
+
667
+ let currentHeight = line ? line.getHeight() : 0;
668
+ let maxHeight = node.maxHeight || -1;
669
+
670
+ if (line) {
671
+ let nodeId = (0, _node.getNodeId)(node);
672
+
673
+ if (nodeId) {
674
+ line.id = nodeId;
675
+ }
676
+ }
677
+
678
+ if (node._tocItemRef) {
679
+ line._pageNodeRef = node._tocItemRef;
680
+ }
681
+
682
+ if (node._pageRef) {
683
+ line._pageNodeRef = node._pageRef._nodeRef;
684
+ }
685
+
686
+ if (line && line.inlines && Array.isArray(line.inlines)) {
687
+ for (let i = 0, l = line.inlines.length; i < l; i++) {
688
+ if (line.inlines[i]._tocItemRef) {
689
+ line.inlines[i]._pageNodeRef = line.inlines[i]._tocItemRef;
690
+ }
691
+
692
+ if (line.inlines[i]._pageRef) {
693
+ line.inlines[i]._pageNodeRef = line.inlines[i]._pageRef._nodeRef;
694
+ }
695
+ }
696
+ }
697
+
698
+ while (line && (maxHeight === -1 || currentHeight < maxHeight)) {
699
+ let positions = this.writer.addLine(line);
700
+ node.positions.push(positions);
701
+ line = this.buildNextLine(node);
702
+
703
+ if (line) {
704
+ currentHeight += line.getHeight();
705
+ }
706
+ }
707
+ }
708
+
709
+ processToc(node) {
710
+ if (node.toc.title) {
711
+ this.processNode(node.toc.title);
712
+ }
713
+
714
+ if (node.toc._table) {
715
+ this.processNode(node.toc._table);
716
+ }
717
+ }
718
+
719
+ buildNextLine(textNode) {
720
+ function cloneInline(inline) {
721
+ let newInline = inline.constructor();
722
+
723
+ for (let key in inline) {
724
+ newInline[key] = inline[key];
725
+ }
726
+
727
+ return newInline;
728
+ }
729
+
730
+ if (!textNode._inlines || textNode._inlines.length === 0) {
731
+ return null;
732
+ }
733
+
734
+ let line = new _Line.default(this.writer.context().availableWidth);
735
+ const textInlines = new _TextInlines.default(null);
736
+ let isForceContinue = false;
737
+
738
+ while (textNode._inlines && textNode._inlines.length > 0 && (line.hasEnoughSpaceForInline(textNode._inlines[0], textNode._inlines.slice(1)) || isForceContinue)) {
739
+ let isHardWrap = false;
740
+
741
+ let inline = textNode._inlines.shift();
742
+
743
+ isForceContinue = false;
744
+
745
+ if (!inline.noWrap && inline.text.length > 1 && inline.width > line.getAvailableWidth()) {
746
+ let widthPerChar = inline.width / inline.text.length;
747
+ let maxChars = Math.floor(line.getAvailableWidth() / widthPerChar);
748
+
749
+ if (maxChars < 1) {
750
+ maxChars = 1;
751
+ }
752
+
753
+ if (maxChars < inline.text.length) {
754
+ let newInline = cloneInline(inline);
755
+ newInline.text = inline.text.substr(maxChars);
756
+ inline.text = inline.text.substr(0, maxChars);
757
+ newInline.width = textInlines.widthOfText(newInline.text, newInline);
758
+ inline.width = textInlines.widthOfText(inline.text, inline);
759
+
760
+ textNode._inlines.unshift(newInline);
761
+
762
+ isHardWrap = true;
763
+ }
764
+ }
765
+
766
+ line.addInline(inline);
767
+ isForceContinue = inline.noNewLine && !isHardWrap;
768
+ }
769
+
770
+ line.lastLineInParagraph = textNode._inlines.length === 0;
771
+ return line;
772
+ } // images
773
+
774
+
775
+ processImage(node) {
776
+ let position = this.writer.addImage(node);
777
+ node.positions.push(position);
778
+ }
779
+
780
+ processCanvas(node) {
781
+ let positions = this.writer.addCanvas(node);
782
+ addAll(node.positions, positions);
783
+ }
784
+
785
+ processSVG(node) {
786
+ let position = this.writer.addSVG(node);
787
+ node.positions.push(position);
788
+ }
789
+
790
+ processQr(node) {
791
+ let position = this.writer.addQr(node);
792
+ node.positions.push(position);
793
+ }
794
+
795
+ processAttachment(node) {
796
+ let position = this.writer.addAttachment(node);
797
+ node.positions.push(position);
798
+ }
799
+
800
+ }
801
+
802
+ function decorateNode(node) {
803
+ let x = node.x;
804
+ let y = node.y;
805
+ node.positions = [];
806
+
807
+ if (Array.isArray(node.canvas)) {
808
+ node.canvas.forEach(vector => {
809
+ let x = vector.x;
810
+ let y = vector.y;
811
+ let x1 = vector.x1;
812
+ let y1 = vector.y1;
813
+ let x2 = vector.x2;
814
+ let y2 = vector.y2;
815
+
816
+ vector.resetXY = () => {
817
+ vector.x = x;
818
+ vector.y = y;
819
+ vector.x1 = x1;
820
+ vector.y1 = y1;
821
+ vector.x2 = x2;
822
+ vector.y2 = y2;
823
+ };
824
+ });
825
+ }
826
+
827
+ node.resetXY = () => {
828
+ node.x = x;
829
+ node.y = y;
830
+
831
+ if (Array.isArray(node.canvas)) {
832
+ node.canvas.forEach(vector => {
833
+ vector.resetXY();
834
+ });
835
+ }
836
+ };
837
+ }
838
+
839
+ var _default = LayoutBuilder;
840
+ exports.default = _default;