pdfmake 0.2.4 → 0.3.0-beta.1

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 +8 -30
  2. package/README.md +8 -6
  3. package/build/pdfmake.js +28921 -26825
  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 +750 -0
  22. package/js/DocPreprocessor.js +285 -0
  23. package/js/DocumentContext.js +306 -0
  24. package/js/ElementWriter.js +377 -0
  25. package/js/LayoutBuilder.js +833 -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 +163 -0
  30. package/js/PageElementWriter.js +161 -0
  31. package/js/PageSize.js +88 -0
  32. package/js/Printer.js +238 -0
  33. package/js/Renderer.js +433 -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 +79 -0
  41. package/js/base.js +69 -0
  42. package/js/browser-extensions/OutputDocumentBrowser.js +131 -0
  43. package/js/browser-extensions/URLBrowserResolver.js +89 -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 +694 -0
  65. package/src/DocPreprocessor.js +258 -0
  66. package/src/DocumentContext.js +309 -0
  67. package/src/ElementWriter.js +368 -0
  68. package/src/LayoutBuilder.js +814 -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 +148 -0
  73. package/src/PageElementWriter.js +156 -0
  74. package/src/PageSize.js +53 -0
  75. package/src/Printer.js +220 -0
  76. package/src/Renderer.js +370 -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 +69 -0
  84. package/src/base.js +61 -0
  85. package/src/browser-extensions/OutputDocumentBrowser.js +117 -0
  86. package/src/browser-extensions/URLBrowserResolver.js +46 -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,161 @@
1
+ const groupDecorations = line => {
2
+ let groups = [];
3
+ let currentGroup = null;
4
+ for (let i = 0, l = line.inlines.length; i < l; i++) {
5
+ let inline = line.inlines[i];
6
+ let decoration = inline.decoration;
7
+ if (!decoration) {
8
+ currentGroup = null;
9
+ continue;
10
+ }
11
+ if (!Array.isArray(decoration)) {
12
+ decoration = [decoration];
13
+ }
14
+ let color = inline.decorationColor || inline.color || 'black';
15
+ let style = inline.decorationStyle || 'solid';
16
+ for (let ii = 0, ll = decoration.length; ii < ll; ii++) {
17
+ let decorationItem = decoration[ii];
18
+ if (!currentGroup || decorationItem !== currentGroup.decoration ||
19
+ style !== currentGroup.decorationStyle || color !== currentGroup.decorationColor) {
20
+
21
+ currentGroup = {
22
+ line: line,
23
+ decoration: decorationItem,
24
+ decorationColor: color,
25
+ decorationStyle: style,
26
+ inlines: [inline]
27
+ };
28
+ groups.push(currentGroup);
29
+ } else {
30
+ currentGroup.inlines.push(inline);
31
+ }
32
+ }
33
+ }
34
+
35
+ return groups;
36
+ };
37
+
38
+ class TextDecorator {
39
+
40
+ constructor(pdfDocument) {
41
+ this.pdfDocument = pdfDocument;
42
+ }
43
+
44
+ drawBackground(line, x, y) {
45
+ let height = line.getHeight();
46
+ for (let i = 0, l = line.inlines.length; i < l; i++) {
47
+ let inline = line.inlines[i];
48
+ if (!inline.background) {
49
+ continue;
50
+ }
51
+
52
+ let color = inline.background;
53
+ let patternColor = this.pdfDocument.providePattern(inline.background);
54
+ if (patternColor !== null) {
55
+ color = patternColor;
56
+ }
57
+
58
+ let justifyShift = (inline.justifyShift || 0);
59
+ this.pdfDocument.fillColor(color)
60
+ .rect(x + inline.x - justifyShift, y, inline.width + justifyShift, height)
61
+ .fill();
62
+ }
63
+ }
64
+
65
+ drawDecorations(line, x, y) {
66
+ let groups = groupDecorations(line);
67
+ for (let i = 0, l = groups.length; i < l; i++) {
68
+ this._drawDecoration(groups[i], x, y);
69
+ }
70
+ }
71
+
72
+ _drawDecoration(group, x, y) {
73
+ const maxInline = () => {
74
+ let max = 0;
75
+ for (let i = 0, l = group.inlines.length; i < l; i++) {
76
+ let inline = group.inlines[i];
77
+ max = inline.fontSize > max ? i : max;
78
+ }
79
+ return group.inlines[max];
80
+ };
81
+
82
+ const width = () => {
83
+ let sum = 0;
84
+ for (let i = 0, l = group.inlines.length; i < l; i++) {
85
+ let justifyShift = (group.inlines[i].justifyShift || 0);
86
+ sum += group.inlines[i].width + justifyShift;
87
+ }
88
+ return sum;
89
+ };
90
+
91
+ let firstInline = group.inlines[0];
92
+ let biggerInline = maxInline();
93
+ let totalWidth = width();
94
+ let lineAscent = group.line.getAscenderHeight();
95
+ let ascent = biggerInline.font.ascender / 1000 * biggerInline.fontSize;
96
+ let height = biggerInline.height;
97
+ let descent = height - ascent;
98
+
99
+ let lw = 0.5 + Math.floor(Math.max(biggerInline.fontSize - 8, 0) / 2) * 0.12;
100
+
101
+ switch (group.decoration) {
102
+ case 'underline':
103
+ y += lineAscent + descent * 0.45;
104
+ break;
105
+ case 'overline':
106
+ y += lineAscent - (ascent * 0.85);
107
+ break;
108
+ case 'lineThrough':
109
+ y += lineAscent - (ascent * 0.25);
110
+ break;
111
+ default:
112
+ throw new Error(`Unkown decoration : ${group.decoration}`);
113
+ }
114
+ this.pdfDocument.save();
115
+
116
+ if (group.decorationStyle === 'double') {
117
+ let gap = Math.max(0.5, lw * 2);
118
+ this.pdfDocument.fillColor(group.decorationColor)
119
+ .rect(x + firstInline.x, y - lw / 2, totalWidth, lw / 2).fill()
120
+ .rect(x + firstInline.x, y + gap - lw / 2, totalWidth, lw / 2).fill();
121
+ } else if (group.decorationStyle === 'dashed') {
122
+ let nbDashes = Math.ceil(totalWidth / (3.96 + 2.84));
123
+ let rdx = x + firstInline.x;
124
+ this.pdfDocument.rect(rdx, y, totalWidth, lw).clip();
125
+ this.pdfDocument.fillColor(group.decorationColor);
126
+ for (let i = 0; i < nbDashes; i++) {
127
+ this.pdfDocument.rect(rdx, y - lw / 2, 3.96, lw).fill();
128
+ rdx += 3.96 + 2.84;
129
+ }
130
+ } else if (group.decorationStyle === 'dotted') {
131
+ let nbDots = Math.ceil(totalWidth / (lw * 3));
132
+ let rx = x + firstInline.x;
133
+ this.pdfDocument.rect(rx, y, totalWidth, lw).clip();
134
+ this.pdfDocument.fillColor(group.decorationColor);
135
+ for (let i = 0; i < nbDots; i++) {
136
+ this.pdfDocument.rect(rx, y - lw / 2, lw, lw).fill();
137
+ rx += (lw * 3);
138
+ }
139
+ } else if (group.decorationStyle === 'wavy') {
140
+ let sh = 0.7, sv = 1;
141
+ let nbWaves = Math.ceil(totalWidth / (sh * 2)) + 1;
142
+ let rwx = x + firstInline.x - 1;
143
+ this.pdfDocument.rect(x + firstInline.x, y - sv, totalWidth, y + sv).clip();
144
+ this.pdfDocument.lineWidth(0.24);
145
+ this.pdfDocument.moveTo(rwx, y);
146
+ for (let i = 0; i < nbWaves; i++) {
147
+ this.pdfDocument.bezierCurveTo(rwx + sh, y - sv, rwx + sh * 2, y - sv, rwx + sh * 3, y)
148
+ .bezierCurveTo(rwx + sh * 4, y + sv, rwx + sh * 5, y + sv, rwx + sh * 6, y);
149
+ rwx += sh * 6;
150
+ }
151
+ this.pdfDocument.stroke(group.decorationColor);
152
+ } else {
153
+ this.pdfDocument.fillColor(group.decorationColor)
154
+ .rect(x + firstInline.x, y - lw / 2, totalWidth, lw)
155
+ .fill();
156
+ }
157
+ this.pdfDocument.restore();
158
+ }
159
+ }
160
+
161
+ export default TextDecorator;
@@ -0,0 +1,223 @@
1
+ import TextBreaker from './TextBreaker';
2
+ import StyleContextStack from './StyleContextStack';
3
+
4
+ const LEADING = /^(\s)+/g;
5
+ const TRAILING = /(\s)+$/g;
6
+
7
+ /**
8
+ * @param {Array} array
9
+ * @returns {Array}
10
+ */
11
+ const flattenTextArray = array => {
12
+ function flatten(array) {
13
+ return array.reduce((prev, cur) => {
14
+ let current = Array.isArray(cur.text) ? flatten(cur.text) : cur;
15
+ let more = [].concat(current).some(Array.isArray);
16
+ return prev.concat(more ? flatten(current) : current);
17
+ }, []);
18
+ }
19
+
20
+ if (!Array.isArray(array)) {
21
+ array = [array];
22
+ }
23
+
24
+ // TODO: Styling in nested text (issue: https://github.com/bpampuch/pdfmake/issues/1174)
25
+
26
+ array = flatten(array);
27
+
28
+ return array;
29
+ };
30
+
31
+
32
+ /**
33
+ * Text measurement utility
34
+ */
35
+ class TextInlines {
36
+
37
+ /**
38
+ * @param {object} pdfDocument object is instance of PDFDocument
39
+ */
40
+ constructor(pdfDocument) {
41
+ this.pdfDocument = pdfDocument;
42
+ }
43
+
44
+ /**
45
+ * Converts an array of strings (or inline-definition-objects) into a collection
46
+ * of inlines and calculated minWidth/maxWidth and their min/max widths
47
+ *
48
+ * @param {Array} textArray an array of inline-definition-objects (or strings)
49
+ * @param {StyleContextStack} styleContextStack current style stack
50
+ * @returns {object} collection of inlines, minWidth, maxWidth
51
+ */
52
+ buildInlines(textArray, styleContextStack) {
53
+ const getTrimmedWidth = item => {
54
+ return Math.max(0, item.width - item.leadingCut - item.trailingCut);
55
+ };
56
+
57
+ let minWidth = 0;
58
+ let maxWidth = 0;
59
+ let currentLineWidth;
60
+
61
+ let flattenedTextArray = flattenTextArray(textArray);
62
+
63
+ const textBreaker = new TextBreaker();
64
+ let breakedText = textBreaker.getBreaks(flattenedTextArray, styleContextStack);
65
+
66
+ let measuredText = this.measure(breakedText, styleContextStack);
67
+
68
+ measuredText.forEach(inline => {
69
+ minWidth = Math.max(minWidth, getTrimmedWidth(inline));
70
+
71
+ if (!currentLineWidth) {
72
+ currentLineWidth = { width: 0, leadingCut: inline.leadingCut, trailingCut: 0 };
73
+ }
74
+
75
+ currentLineWidth.width += inline.width;
76
+ currentLineWidth.trailingCut = inline.trailingCut;
77
+
78
+ maxWidth = Math.max(maxWidth, getTrimmedWidth(currentLineWidth));
79
+
80
+ if (inline.lineEnd) {
81
+ currentLineWidth = null;
82
+ }
83
+ });
84
+
85
+ if (StyleContextStack.getStyleProperty({}, styleContextStack, 'noWrap', false)) {
86
+ minWidth = maxWidth;
87
+ }
88
+
89
+ return {
90
+ items: measuredText,
91
+ minWidth: minWidth,
92
+ maxWidth: maxWidth
93
+ };
94
+ }
95
+
96
+ measure(array, styleContextStack) {
97
+ if (array.length) {
98
+ let leadingIndent = StyleContextStack.getStyleProperty(array[0], styleContextStack, 'leadingIndent', 0);
99
+ if (leadingIndent) {
100
+ array[0].leadingCut = -leadingIndent;
101
+ array[0].leadingIndent = leadingIndent;
102
+ }
103
+ }
104
+
105
+ array.forEach(item => {
106
+ let font = StyleContextStack.getStyleProperty(item, styleContextStack, 'font', 'Roboto');
107
+ let bold = StyleContextStack.getStyleProperty(item, styleContextStack, 'bold', false);
108
+ let italics = StyleContextStack.getStyleProperty(item, styleContextStack, 'italics', false);
109
+
110
+ item.font = this.pdfDocument.provideFont(font, bold, italics);
111
+
112
+ item.alignment = StyleContextStack.getStyleProperty(item, styleContextStack, 'alignment', 'left');
113
+ item.fontSize = StyleContextStack.getStyleProperty(item, styleContextStack, 'fontSize', 12);
114
+ item.fontFeatures = StyleContextStack.getStyleProperty(item, styleContextStack, 'fontFeatures', null);
115
+ item.characterSpacing = StyleContextStack.getStyleProperty(item, styleContextStack, 'characterSpacing', 0);
116
+ item.color = StyleContextStack.getStyleProperty(item, styleContextStack, 'color', 'black');
117
+ item.decoration = StyleContextStack.getStyleProperty(item, styleContextStack, 'decoration', null);
118
+ item.decorationColor = StyleContextStack.getStyleProperty(item, styleContextStack, 'decorationColor', null);
119
+ item.decorationStyle = StyleContextStack.getStyleProperty(item, styleContextStack, 'decorationStyle', null);
120
+ item.background = StyleContextStack.getStyleProperty(item, styleContextStack, 'background', null);
121
+ item.link = StyleContextStack.getStyleProperty(item, styleContextStack, 'link', null);
122
+ item.linkToPage = StyleContextStack.getStyleProperty(item, styleContextStack, 'linkToPage', null);
123
+ item.linkToDestination = StyleContextStack.getStyleProperty(item, styleContextStack, 'linkToDestination', null);
124
+ item.noWrap = StyleContextStack.getStyleProperty(item, styleContextStack, 'noWrap', null);
125
+ item.opacity = StyleContextStack.getStyleProperty(item, styleContextStack, 'opacity', 1);
126
+ item.sup = StyleContextStack.getStyleProperty(item, styleContextStack, 'sup', false);
127
+ item.sub = StyleContextStack.getStyleProperty(item, styleContextStack, 'sub', false);
128
+
129
+ if (item.sup || item.sub) {
130
+ // font size reduction taken from here: https://en.wikipedia.org/wiki/Subscript_and_superscript#Desktop_publishing
131
+ item.fontSize *= 0.58;
132
+ }
133
+
134
+ let lineHeight = StyleContextStack.getStyleProperty(item, styleContextStack, 'lineHeight', 1);
135
+
136
+ item.width = this.widthOfText(item.text, item);
137
+ item.height = item.font.lineHeight(item.fontSize) * lineHeight;
138
+
139
+ if (!item.leadingCut) {
140
+ item.leadingCut = 0;
141
+ }
142
+
143
+ let preserveLeadingSpaces = StyleContextStack.getStyleProperty(item, styleContextStack, 'preserveLeadingSpaces', false);
144
+ if (!preserveLeadingSpaces) {
145
+ let leadingSpaces = item.text.match(LEADING);
146
+ if (leadingSpaces) {
147
+ item.leadingCut += this.widthOfText(leadingSpaces[0], item);
148
+ }
149
+ }
150
+
151
+ item.trailingCut = 0;
152
+
153
+ let preserveTrailingSpaces = StyleContextStack.getStyleProperty(item, styleContextStack, 'preserveTrailingSpaces', false);
154
+ if (!preserveTrailingSpaces) {
155
+ let trailingSpaces = item.text.match(TRAILING);
156
+ if (trailingSpaces) {
157
+ item.trailingCut = this.widthOfText(trailingSpaces[0], item);
158
+ }
159
+ }
160
+ }, this);
161
+
162
+ return array;
163
+ }
164
+
165
+ /**
166
+ * Width of text
167
+ *
168
+ * @param {string} text
169
+ * @param {object} inline
170
+ * @returns {number}
171
+ */
172
+ widthOfText(text, inline) {
173
+ return inline.font.widthOfString(text, inline.fontSize, inline.fontFeatures) + ((inline.characterSpacing || 0) * (text.length - 1));
174
+ }
175
+
176
+ /**
177
+ * Returns size of the specified string (without breaking it) using the current style
178
+ *
179
+ * @param {string} text text to be measured
180
+ * @param {object} styleContextStack current style stack
181
+ * @returns {object} size of the specified string
182
+ */
183
+ sizeOfText(text, styleContextStack) {
184
+ //TODO: refactor - extract from measure
185
+ let fontName = StyleContextStack.getStyleProperty({}, styleContextStack, 'font', 'Roboto');
186
+ let fontSize = StyleContextStack.getStyleProperty({}, styleContextStack, 'fontSize', 12);
187
+ let fontFeatures = StyleContextStack.getStyleProperty({}, styleContextStack, 'fontFeatures', null);
188
+ let bold = StyleContextStack.getStyleProperty({}, styleContextStack, 'bold', false);
189
+ let italics = StyleContextStack.getStyleProperty({}, styleContextStack, 'italics', false);
190
+ let lineHeight = StyleContextStack.getStyleProperty({}, styleContextStack, 'lineHeight', 1);
191
+ let characterSpacing = StyleContextStack.getStyleProperty({}, styleContextStack, 'characterSpacing', 0);
192
+
193
+ let font = this.pdfDocument.provideFont(fontName, bold, italics);
194
+
195
+ return {
196
+ width: this.widthOfText(text, { font: font, fontSize: fontSize, characterSpacing: characterSpacing, fontFeatures: fontFeatures }),
197
+ height: font.lineHeight(fontSize) * lineHeight,
198
+ fontSize: fontSize,
199
+ lineHeight: lineHeight,
200
+ ascender: font.ascender / 1000 * fontSize,
201
+ descender: font.descender / 1000 * fontSize
202
+ };
203
+ }
204
+
205
+ /**
206
+ * Returns size of the specified rotated string (without breaking it) using the current style
207
+ *
208
+ * @param {string} text text to be measured
209
+ * @param {number} angle
210
+ * @param {object} styleContextStack current style stack
211
+ * @returns {object} size of the specified string
212
+ */
213
+ sizeOfRotatedText(text, angle, styleContextStack) {
214
+ let angleRad = angle * Math.PI / -180;
215
+ let size = this.sizeOfText(text, styleContextStack);
216
+ return {
217
+ width: Math.abs(size.height * Math.sin(angleRad)) + Math.abs(size.width * Math.cos(angleRad)),
218
+ height: Math.abs(size.width * Math.sin(angleRad)) + Math.abs(size.height * Math.cos(angleRad))
219
+ };
220
+ }
221
+ }
222
+
223
+ export default TextInlines;
@@ -0,0 +1,69 @@
1
+ import http from 'http';
2
+ import https from 'https';
3
+
4
+ const fetchUrl = url => {
5
+ return new Promise((resolve, reject) => {
6
+ const parsedUrl = new URL(url);
7
+ const h = (parsedUrl.protocol === 'https:') ? https : http;
8
+
9
+ h.get(url, res => {
10
+ if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) { // redirect url
11
+ fetchUrl(res.headers.location).then(buffer => {
12
+ resolve(buffer);
13
+ }, result => {
14
+ reject(result);
15
+ });
16
+ return;
17
+ }
18
+
19
+ const ok = res.statusCode >= 200 && res.statusCode < 300;
20
+ if (!ok) {
21
+ reject(new TypeError(`Failed to fetch (status code: ${res.statusCode}, url: "${url}")`));
22
+ }
23
+
24
+ const chunks = [];
25
+ res.on('end', () => resolve(Buffer.concat(chunks)));
26
+ res.on('data', d => chunks.push(d));
27
+ }).on('error', reject);
28
+ });
29
+ };
30
+
31
+ class URLResolver {
32
+ constructor(fs) {
33
+ this.fs = fs;
34
+ this.resolving = {};
35
+ }
36
+
37
+ resolve(url) {
38
+ if (!this.resolving[url]) {
39
+ this.resolving[url] = new Promise((resolve, reject) => {
40
+ if (url.toLowerCase().indexOf('https://') === 0 || url.toLowerCase().indexOf('http://') === 0) {
41
+ fetchUrl(url).then(buffer => {
42
+ this.fs.writeFileSync(url, buffer);
43
+ resolve();
44
+ }, result => {
45
+ reject(result);
46
+ });
47
+ } else {
48
+ // cannot be resolved
49
+ resolve();
50
+ }
51
+ });
52
+ }
53
+
54
+ return this.resolving[url];
55
+ }
56
+
57
+ resolved() {
58
+ return new Promise((resolve, reject) => {
59
+ Promise.all(Object.values(this.resolving)).then(() => {
60
+ resolve();
61
+ }, result => {
62
+ reject(result);
63
+ });
64
+ });
65
+ }
66
+
67
+ }
68
+
69
+ export default URLResolver;
package/src/base.js ADDED
@@ -0,0 +1,61 @@
1
+ import Printer from './Printer';
2
+ import virtualfs from './virtual-fs';
3
+ import { pack } from './helpers/tools';
4
+
5
+ class pdfmake {
6
+
7
+ constructor() {
8
+ this.virtualfs = virtualfs;
9
+ this.urlResolver = null;
10
+ }
11
+
12
+ /**
13
+ * @param {object} docDefinition
14
+ * @param {?object} options
15
+ * @returns {object}
16
+ */
17
+ createPdf(docDefinition, options = {}) {
18
+ options.progressCallback = this.progressCallback;
19
+ options.tableLayouts = this.tableLayouts;
20
+
21
+ let printer = new Printer(this.fonts, this.virtualfs, this.urlResolver);
22
+ const pdfDocumentPromise = printer.createPdfKitDocument(docDefinition, options);
23
+
24
+ return this._transformToDocument(pdfDocumentPromise);
25
+ }
26
+
27
+ setProgressCallback(callback) {
28
+ this.progressCallback = callback;
29
+ }
30
+
31
+ addTableLayouts(tableLayouts) {
32
+ this.tableLayouts = pack(this.tableLayouts, tableLayouts);
33
+ }
34
+
35
+ setTableLayouts(tableLayouts) {
36
+ this.tableLayouts = tableLayouts;
37
+ }
38
+
39
+ clearTableLayouts() {
40
+ this.tableLayouts = {};
41
+ }
42
+
43
+ addFonts(fonts) {
44
+ this.fonts = pack(this.fonts, fonts);
45
+ }
46
+
47
+ setFonts(fonts) {
48
+ this.fonts = fonts;
49
+ }
50
+
51
+ clearFonts() {
52
+ this.fonts = {};
53
+ }
54
+
55
+ _transformToDocument(doc) {
56
+ return doc;
57
+ }
58
+
59
+ }
60
+
61
+ export default pdfmake;
@@ -0,0 +1,117 @@
1
+ import OutputDocument from '../OutputDocument';
2
+ import { saveAs } from 'file-saver';
3
+
4
+ /**
5
+ * @returns {Window}
6
+ */
7
+ const openWindow = () => {
8
+ // we have to open the window immediately and store the reference
9
+ // otherwise popup blockers will stop us
10
+ let win = window.open('', '_blank');
11
+ if (win === null) {
12
+ throw new Error('Open PDF in new window blocked by browser');
13
+ }
14
+
15
+ return win;
16
+ };
17
+
18
+ class OutputDocumentBrowser extends OutputDocument {
19
+
20
+ /**
21
+ * @returns {Promise<Blob>}
22
+ */
23
+ getBlob() {
24
+ return new Promise((resolve, reject) => {
25
+ this.getBuffer().then(buffer => {
26
+ try {
27
+ let blob = new Blob([buffer], { type: 'application/pdf' });
28
+ resolve(blob);
29
+ } catch (e) {
30
+ reject(e);
31
+ }
32
+ }, result => {
33
+ reject(result);
34
+ });
35
+ });
36
+ }
37
+
38
+ /**
39
+ * @param {string} filename
40
+ * @returns {Promise}
41
+ */
42
+ download(filename = 'file.pdf') {
43
+ return new Promise((resolve, reject) => {
44
+ this.getBlob().then(blob => {
45
+ try {
46
+ saveAs(blob, filename);
47
+ resolve();
48
+ } catch (e) {
49
+ reject(e);
50
+ }
51
+ }, result => {
52
+ reject(result);
53
+ });
54
+ });
55
+ }
56
+
57
+ /**
58
+ * @param {Window} win
59
+ * @returns {Promise}
60
+ */
61
+ open(win = null) {
62
+ return new Promise((resolve, reject) => {
63
+ if (!win) {
64
+ win = openWindow();
65
+ }
66
+ this.getBlob().then(blob => {
67
+ try {
68
+ let urlCreator = window.URL || window.webkitURL;
69
+ let pdfUrl = urlCreator.createObjectURL(blob);
70
+ win.location.href = pdfUrl;
71
+
72
+ //
73
+ resolve();
74
+ /* temporarily disabled
75
+ if (win === window) {
76
+ resolve();
77
+ } else {
78
+ setTimeout(() => {
79
+ if (win.window === null) { // is closed by AdBlock
80
+ window.location.href = pdfUrl; // open in actual window
81
+ }
82
+ resolve();
83
+ }, 500);
84
+ }
85
+ */
86
+ } catch (e) {
87
+ win.close();
88
+ reject(e);
89
+ }
90
+ }, result => {
91
+ reject(result);
92
+ });
93
+ });
94
+ }
95
+
96
+ /**
97
+ * @param {Window} win
98
+ * @returns {Promise}
99
+ */
100
+ print(win = null) {
101
+ return new Promise((resolve, reject) => {
102
+ this.getStream().then(stream => {
103
+ stream.setOpenActionAsPrint();
104
+ return this.open(win).then(() => {
105
+ resolve();
106
+ }, result => {
107
+ reject(result);
108
+ });
109
+ }, result => {
110
+ reject(result);
111
+ });
112
+ });
113
+ }
114
+
115
+ }
116
+
117
+ export default OutputDocumentBrowser;