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/src/TextInlines.js
CHANGED
|
@@ -1,223 +1,224 @@
|
|
|
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|object} 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 brokenText = textBreaker.getBreaks(flattenedTextArray, styleContextStack);
|
|
65
|
-
|
|
66
|
-
let measuredText = this.measure(brokenText, 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.
|
|
121
|
-
item.
|
|
122
|
-
item.
|
|
123
|
-
item.
|
|
124
|
-
item.
|
|
125
|
-
item.
|
|
126
|
-
item.
|
|
127
|
-
item.
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
item.
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
*
|
|
168
|
-
*
|
|
169
|
-
* @param {
|
|
170
|
-
* @
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
*
|
|
179
|
-
*
|
|
180
|
-
* @param {
|
|
181
|
-
* @
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
let
|
|
187
|
-
let
|
|
188
|
-
let
|
|
189
|
-
let
|
|
190
|
-
let
|
|
191
|
-
let
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
*
|
|
208
|
-
*
|
|
209
|
-
* @param {
|
|
210
|
-
* @param {
|
|
211
|
-
* @
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
let
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
}
|
|
222
|
-
|
|
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|object} 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 brokenText = textBreaker.getBreaks(flattenedTextArray, styleContextStack);
|
|
65
|
+
|
|
66
|
+
let measuredText = this.measure(brokenText, 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.decorationThickness = StyleContextStack.getStyleProperty(item, styleContextStack, 'decorationThickness', null);
|
|
121
|
+
item.background = StyleContextStack.getStyleProperty(item, styleContextStack, 'background', null);
|
|
122
|
+
item.link = StyleContextStack.getStyleProperty(item, styleContextStack, 'link', null);
|
|
123
|
+
item.linkToPage = StyleContextStack.getStyleProperty(item, styleContextStack, 'linkToPage', null);
|
|
124
|
+
item.linkToDestination = StyleContextStack.getStyleProperty(item, styleContextStack, 'linkToDestination', null);
|
|
125
|
+
item.noWrap = StyleContextStack.getStyleProperty(item, styleContextStack, 'noWrap', null);
|
|
126
|
+
item.opacity = StyleContextStack.getStyleProperty(item, styleContextStack, 'opacity', 1);
|
|
127
|
+
item.sup = StyleContextStack.getStyleProperty(item, styleContextStack, 'sup', false);
|
|
128
|
+
item.sub = StyleContextStack.getStyleProperty(item, styleContextStack, 'sub', false);
|
|
129
|
+
|
|
130
|
+
if (item.sup || item.sub) {
|
|
131
|
+
// font size reduction taken from here: https://en.wikipedia.org/wiki/Subscript_and_superscript#Desktop_publishing
|
|
132
|
+
item.fontSize *= 0.58;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
let lineHeight = StyleContextStack.getStyleProperty(item, styleContextStack, 'lineHeight', 1);
|
|
136
|
+
|
|
137
|
+
item.width = this.widthOfText(item.text, item);
|
|
138
|
+
item.height = item.font.lineHeight(item.fontSize) * lineHeight;
|
|
139
|
+
|
|
140
|
+
if (!item.leadingCut) {
|
|
141
|
+
item.leadingCut = 0;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
let preserveLeadingSpaces = StyleContextStack.getStyleProperty(item, styleContextStack, 'preserveLeadingSpaces', false);
|
|
145
|
+
if (!preserveLeadingSpaces) {
|
|
146
|
+
let leadingSpaces = item.text.match(LEADING);
|
|
147
|
+
if (leadingSpaces) {
|
|
148
|
+
item.leadingCut += this.widthOfText(leadingSpaces[0], item);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
item.trailingCut = 0;
|
|
153
|
+
|
|
154
|
+
let preserveTrailingSpaces = StyleContextStack.getStyleProperty(item, styleContextStack, 'preserveTrailingSpaces', false);
|
|
155
|
+
if (!preserveTrailingSpaces) {
|
|
156
|
+
let trailingSpaces = item.text.match(TRAILING);
|
|
157
|
+
if (trailingSpaces) {
|
|
158
|
+
item.trailingCut = this.widthOfText(trailingSpaces[0], item);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}, this);
|
|
162
|
+
|
|
163
|
+
return array;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Width of text
|
|
168
|
+
*
|
|
169
|
+
* @param {string} text
|
|
170
|
+
* @param {object} inline
|
|
171
|
+
* @returns {number}
|
|
172
|
+
*/
|
|
173
|
+
widthOfText(text, inline) {
|
|
174
|
+
return inline.font.widthOfString(text, inline.fontSize, inline.fontFeatures) + ((inline.characterSpacing || 0) * (text.length - 1));
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Returns size of the specified string (without breaking it) using the current style
|
|
179
|
+
*
|
|
180
|
+
* @param {string} text text to be measured
|
|
181
|
+
* @param {object} styleContextStack current style stack
|
|
182
|
+
* @returns {object} size of the specified string
|
|
183
|
+
*/
|
|
184
|
+
sizeOfText(text, styleContextStack) {
|
|
185
|
+
//TODO: refactor - extract from measure
|
|
186
|
+
let fontName = StyleContextStack.getStyleProperty({}, styleContextStack, 'font', 'Roboto');
|
|
187
|
+
let fontSize = StyleContextStack.getStyleProperty({}, styleContextStack, 'fontSize', 12);
|
|
188
|
+
let fontFeatures = StyleContextStack.getStyleProperty({}, styleContextStack, 'fontFeatures', null);
|
|
189
|
+
let bold = StyleContextStack.getStyleProperty({}, styleContextStack, 'bold', false);
|
|
190
|
+
let italics = StyleContextStack.getStyleProperty({}, styleContextStack, 'italics', false);
|
|
191
|
+
let lineHeight = StyleContextStack.getStyleProperty({}, styleContextStack, 'lineHeight', 1);
|
|
192
|
+
let characterSpacing = StyleContextStack.getStyleProperty({}, styleContextStack, 'characterSpacing', 0);
|
|
193
|
+
|
|
194
|
+
let font = this.pdfDocument.provideFont(fontName, bold, italics);
|
|
195
|
+
|
|
196
|
+
return {
|
|
197
|
+
width: this.widthOfText(text, { font: font, fontSize: fontSize, characterSpacing: characterSpacing, fontFeatures: fontFeatures }),
|
|
198
|
+
height: font.lineHeight(fontSize) * lineHeight,
|
|
199
|
+
fontSize: fontSize,
|
|
200
|
+
lineHeight: lineHeight,
|
|
201
|
+
ascender: font.ascender / 1000 * fontSize,
|
|
202
|
+
descender: font.descender / 1000 * fontSize
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Returns size of the specified rotated string (without breaking it) using the current style
|
|
208
|
+
*
|
|
209
|
+
* @param {string} text text to be measured
|
|
210
|
+
* @param {number} angle
|
|
211
|
+
* @param {object} styleContextStack current style stack
|
|
212
|
+
* @returns {object} size of the specified string
|
|
213
|
+
*/
|
|
214
|
+
sizeOfRotatedText(text, angle, styleContextStack) {
|
|
215
|
+
let angleRad = angle * Math.PI / -180;
|
|
216
|
+
let size = this.sizeOfText(text, styleContextStack);
|
|
217
|
+
return {
|
|
218
|
+
width: Math.abs(size.height * Math.sin(angleRad)) + Math.abs(size.width * Math.cos(angleRad)),
|
|
219
|
+
height: Math.abs(size.width * Math.sin(angleRad)) + Math.abs(size.height * Math.cos(angleRad))
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
export default TextInlines;
|
package/src/URLResolver.js
CHANGED
|
@@ -1,43 +1,43 @@
|
|
|
1
|
-
async function fetchUrl(url, headers = {}) {
|
|
2
|
-
try {
|
|
3
|
-
const response = await fetch(url, { headers });
|
|
4
|
-
if (!response.ok) {
|
|
5
|
-
throw new Error(`Failed to fetch (status code: ${response.status}, url: "${url}")`);
|
|
6
|
-
}
|
|
7
|
-
return await response.arrayBuffer();
|
|
8
|
-
} catch (error) {
|
|
9
|
-
throw new Error(`Network request failed (url: "${url}", error: ${error.message})`);
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
class URLResolver {
|
|
14
|
-
constructor(fs) {
|
|
15
|
-
this.fs = fs;
|
|
16
|
-
this.resolving = {};
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
resolve(url, headers = {}) {
|
|
20
|
-
const resolveUrlInternal = async () => {
|
|
21
|
-
if (url.toLowerCase().startsWith('https://') || url.toLowerCase().startsWith('http://')) {
|
|
22
|
-
if (this.fs.existsSync(url)) {
|
|
23
|
-
return; // url was downloaded earlier
|
|
24
|
-
}
|
|
25
|
-
const buffer = await fetchUrl(url, headers);
|
|
26
|
-
this.fs.writeFileSync(url, buffer);
|
|
27
|
-
}
|
|
28
|
-
// else cannot be resolved
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
if (!this.resolving[url]) {
|
|
32
|
-
this.resolving[url] = resolveUrlInternal();
|
|
33
|
-
}
|
|
34
|
-
return this.resolving[url];
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
resolved() {
|
|
38
|
-
return Promise.all(Object.values(this.resolving));
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export default URLResolver;
|
|
1
|
+
async function fetchUrl(url, headers = {}) {
|
|
2
|
+
try {
|
|
3
|
+
const response = await fetch(url, { headers });
|
|
4
|
+
if (!response.ok) {
|
|
5
|
+
throw new Error(`Failed to fetch (status code: ${response.status}, url: "${url}")`);
|
|
6
|
+
}
|
|
7
|
+
return await response.arrayBuffer();
|
|
8
|
+
} catch (error) {
|
|
9
|
+
throw new Error(`Network request failed (url: "${url}", error: ${error.message})`);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
class URLResolver {
|
|
14
|
+
constructor(fs) {
|
|
15
|
+
this.fs = fs;
|
|
16
|
+
this.resolving = {};
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
resolve(url, headers = {}) {
|
|
20
|
+
const resolveUrlInternal = async () => {
|
|
21
|
+
if (url.toLowerCase().startsWith('https://') || url.toLowerCase().startsWith('http://')) {
|
|
22
|
+
if (this.fs.existsSync(url)) {
|
|
23
|
+
return; // url was downloaded earlier
|
|
24
|
+
}
|
|
25
|
+
const buffer = await fetchUrl(url, headers);
|
|
26
|
+
this.fs.writeFileSync(url, buffer);
|
|
27
|
+
}
|
|
28
|
+
// else cannot be resolved
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
if (!this.resolving[url]) {
|
|
32
|
+
this.resolving[url] = resolveUrlInternal();
|
|
33
|
+
}
|
|
34
|
+
return this.resolving[url];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
resolved() {
|
|
38
|
+
return Promise.all(Object.values(this.resolving));
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export default URLResolver;
|