cvdl-ts 1.0.14 → 1.0.16
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/dist/Elem.d.ts +2 -5
- package/dist/Elem.js +1 -52
- package/dist/Layout.d.ts +0 -7
- package/dist/Layout.js +39 -95
- package/dist/PdfLayout.d.ts +9 -1
- package/dist/PdfLayout.js +42 -34
- package/dist/Row.d.ts +0 -9
- package/dist/Row.js +6 -73
- package/dist/Stack.d.ts +0 -6
- package/dist/Stack.js +4 -44
- package/dist/Utils.d.ts +1 -1
- package/dist/Utils.js +7 -2
- package/package.json +1 -1
package/dist/Elem.d.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import * as Font from "./Font";
|
|
2
|
-
import { Alignment,
|
|
2
|
+
import { Alignment, Margin, Width } from ".";
|
|
3
3
|
import { Color } from "./Layout";
|
|
4
4
|
import { FontDict } from "./AnyLayout";
|
|
5
|
-
import * as Row from "./Row";
|
|
6
5
|
import { ItemContent } from "./Resume";
|
|
7
6
|
import { Field } from "./DataSchema";
|
|
8
7
|
import { Optional } from "./Utils";
|
|
@@ -50,7 +49,7 @@ export declare function copy(e: Elem): {
|
|
|
50
49
|
margin: Margin.t;
|
|
51
50
|
alignment: Alignment.t;
|
|
52
51
|
width: Width.t;
|
|
53
|
-
background_color:
|
|
52
|
+
background_color: Color;
|
|
54
53
|
};
|
|
55
54
|
export declare function default_(): Elem;
|
|
56
55
|
export declare function from(w: Optional<Elem>): Elem;
|
|
@@ -68,8 +67,6 @@ export declare function withBackgroundColor(e: Elem, background_color: Color): E
|
|
|
68
67
|
export declare function scaleWidth(e: Elem, scale: number): Elem;
|
|
69
68
|
export declare function parseMarkdownItem(item: string): Span[];
|
|
70
69
|
export declare function fillFonts(e: Elem, fonts: FontDict): Elem;
|
|
71
|
-
export declare function justifiedLines(e: Elem, lines: Elem[], font_dict: FontDict): Row.t[];
|
|
72
|
-
export declare function break_lines(e: Elem, font_dict: FontDict): Layout.t[];
|
|
73
70
|
export declare function boundWidth(e: Elem, width: number): Elem;
|
|
74
71
|
export declare function instantiate(e: Elem, section: Map<string, ItemContent>, fields: Field.t[]): Elem;
|
|
75
72
|
export {};
|
package/dist/Elem.js
CHANGED
|
@@ -23,10 +23,9 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
23
23
|
return result;
|
|
24
24
|
};
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
exports.instantiate = exports.boundWidth = exports.
|
|
26
|
+
exports.instantiate = exports.boundWidth = exports.fillFonts = exports.parseMarkdownItem = exports.scaleWidth = exports.withBackgroundColor = exports.withWidth = exports.withAlignment = exports.withMargin = exports.withFont = exports.withTextWidth = exports.withIsFill = exports.asRef = exports.withIsRef = exports.withUrl = exports.withItem = exports.from = exports.default_ = exports.copy = exports.elem = void 0;
|
|
27
27
|
const Font = __importStar(require("./Font"));
|
|
28
28
|
const _1 = require(".");
|
|
29
|
-
const Row_1 = require("./Row");
|
|
30
29
|
const Resume_1 = require("./Resume");
|
|
31
30
|
const marked = __importStar(require("marked"));
|
|
32
31
|
const ts_pattern_1 = require("ts-pattern");
|
|
@@ -220,56 +219,6 @@ function fillFonts(e, fonts) {
|
|
|
220
219
|
}
|
|
221
220
|
}
|
|
222
221
|
exports.fillFonts = fillFonts;
|
|
223
|
-
function justifiedLines(e, lines, font_dict) {
|
|
224
|
-
const rowLines = [];
|
|
225
|
-
for (const line of lines.slice(0, -1)) {
|
|
226
|
-
const words = line.item.split(/\s+/);
|
|
227
|
-
const r = (0, Row_1.row)([], line.margin, line.alignment, line.width, false, false);
|
|
228
|
-
words.forEach(word => {
|
|
229
|
-
const word_width = Font.get_width(e.font, word, font_dict);
|
|
230
|
-
r.elements.push(elem(word, null, false, false, false, _1.Width.absolute(word_width), this.font, _1.Margin.default_(), _1.Alignment.default_(), _1.Width.absolute(word_width), this.background_color));
|
|
231
|
-
});
|
|
232
|
-
rowLines.push(Row_1.row);
|
|
233
|
-
}
|
|
234
|
-
rowLines.push((0, Row_1.row)([withAlignment(lines[lines.length - 1], "Left")], lines[0].margin, "Left", lines[0].width, false, false));
|
|
235
|
-
return rowLines;
|
|
236
|
-
}
|
|
237
|
-
exports.justifiedLines = justifiedLines;
|
|
238
|
-
function break_lines(e, font_dict) {
|
|
239
|
-
if (_1.Width.get_fixed_unchecked(e.text_width) <= _1.Width.get_fixed_unchecked(e.width)) {
|
|
240
|
-
return [e];
|
|
241
|
-
}
|
|
242
|
-
const lines = [];
|
|
243
|
-
// todo: I'm sure this implementation is pretty buggy. Note to future me, fix
|
|
244
|
-
// this.
|
|
245
|
-
const words = e.text.split(/\s+/);
|
|
246
|
-
const widths = words.map((word) => Font.get_width(e.font, word, font_dict));
|
|
247
|
-
const space_width = Font.get_width(e.font, " ", font_dict);
|
|
248
|
-
let start = 0;
|
|
249
|
-
let width = widths[0];
|
|
250
|
-
const max_width = _1.Width.get_fixed_unchecked(e.width);
|
|
251
|
-
for (let i = 1; i < words.length; i++) {
|
|
252
|
-
const candidate_width = width + space_width + widths[i];
|
|
253
|
-
if (candidate_width > max_width) {
|
|
254
|
-
const line = words.slice(start, i).join(" ");
|
|
255
|
-
const line_width = Font.get_width(e.font, line, font_dict);
|
|
256
|
-
lines.push(withTextWidth(withItem(e, line), _1.Width.absolute(line_width)));
|
|
257
|
-
start = i;
|
|
258
|
-
width = widths[i];
|
|
259
|
-
}
|
|
260
|
-
else {
|
|
261
|
-
width += space_width + widths[i];
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
const line = words.slice(start).join(" ");
|
|
265
|
-
const line_width = Font.get_width(e.font, line, font_dict);
|
|
266
|
-
lines.push(withTextWidth(withItem(e, line), _1.Width.absolute(line_width)));
|
|
267
|
-
if (e.alignment === "Justified") {
|
|
268
|
-
return justifiedLines(e, lines, font_dict);
|
|
269
|
-
}
|
|
270
|
-
return lines;
|
|
271
|
-
}
|
|
272
|
-
exports.break_lines = break_lines;
|
|
273
222
|
function boundWidth(e, width) {
|
|
274
223
|
if (!_1.Width.is_fill(e.width)) {
|
|
275
224
|
return withIsFill(withWidth(e, _1.Width.absolute(Math.min(_1.Width.get_fixed_unchecked(e.width), width))), false);
|
package/dist/Layout.d.ts
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
import * as Margin from "./Margin";
|
|
2
|
-
import * as Alignment from "./Alignment";
|
|
3
|
-
import * as Width from "./Width";
|
|
4
1
|
import * as Font from "./Font";
|
|
5
2
|
import { ItemContent } from "./Resume";
|
|
6
3
|
import { Box } from "./Box";
|
|
@@ -37,9 +34,6 @@ export declare function isContainer(l: Layout): boolean;
|
|
|
37
34
|
export declare function isFill(l: Layout): boolean;
|
|
38
35
|
export declare function isRef(l: Layout): boolean;
|
|
39
36
|
export declare function fonts(l: Layout): Font.t[];
|
|
40
|
-
export declare function withMargin(l: Layout, margin: Margin.t): Layout;
|
|
41
|
-
export declare function withAlignment(l: Layout, alignment: Alignment.t): Layout;
|
|
42
|
-
export declare function withWidth(l: Layout, width: Width.t): Layout;
|
|
43
37
|
export declare function totalElementsWidth(l: Layout): number;
|
|
44
38
|
export declare function isInstantiated(l: Layout): boolean;
|
|
45
39
|
export declare function instantiate(l: Layout, section: Map<string, ItemContent>, fields: Field.t[]): Layout;
|
|
@@ -47,7 +41,6 @@ export declare function boundWidth(l: Layout, width: number): Layout;
|
|
|
47
41
|
export declare function scaleWidth(l: Layout, document_width: number): Layout;
|
|
48
42
|
export declare function normalize(l: Layout, width: number, font_dict: FontDict): Layout;
|
|
49
43
|
export declare function fillFonts(l: Layout, font_dict: FontDict): Layout;
|
|
50
|
-
export declare function breakLines(l: Layout, font_dict: FontDict): Layout;
|
|
51
44
|
export declare function computeBoxes(l: Layout, font_dict: FontDict): RenderedLayout;
|
|
52
45
|
export declare function computeTextboxPositions(l: Layout, top_left: Point, font_dict: FontDict): {
|
|
53
46
|
depth: number;
|
package/dist/Layout.js
CHANGED
|
@@ -23,7 +23,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
23
23
|
return result;
|
|
24
24
|
};
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
exports.ColorMap = exports.computeTextboxPositions = exports.computeBoxes = exports.
|
|
26
|
+
exports.ColorMap = exports.computeTextboxPositions = exports.computeBoxes = exports.fillFonts = exports.normalize = exports.scaleWidth = exports.boundWidth = exports.instantiate = exports.isInstantiated = exports.totalElementsWidth = exports.fonts = exports.isRef = exports.isFill = exports.isContainer = exports.toJson = exports.tag_ = exports.type_ = exports.fromJson = exports.empty = exports.default_ = void 0;
|
|
27
27
|
const Width = __importStar(require("./Width"));
|
|
28
28
|
const Font = __importStar(require("./Font"));
|
|
29
29
|
const Box_1 = require("./Box");
|
|
@@ -31,11 +31,12 @@ const Point_1 = require("./Point");
|
|
|
31
31
|
const Stack = __importStar(require("./Stack"));
|
|
32
32
|
const Row = __importStar(require("./Row"));
|
|
33
33
|
const Elem = __importStar(require("./Elem"));
|
|
34
|
+
const Utils_1 = require("./Utils");
|
|
34
35
|
function default_(tag) {
|
|
35
36
|
switch (tag) {
|
|
36
37
|
case "Stack": return Stack.default_();
|
|
37
38
|
case "FlexRow": return Row.default_();
|
|
38
|
-
case "FrozenRow": return
|
|
39
|
+
case "FrozenRow": return (0, Utils_1.with_)(Row.default_(), { is_frozen: true });
|
|
39
40
|
case "Text": return Elem.default_();
|
|
40
41
|
case "Ref": return Elem.asRef(Elem.default_());
|
|
41
42
|
}
|
|
@@ -157,39 +158,6 @@ function fonts(l) {
|
|
|
157
158
|
}
|
|
158
159
|
}
|
|
159
160
|
exports.fonts = fonts;
|
|
160
|
-
function withMargin(l, margin) {
|
|
161
|
-
switch (l.tag) {
|
|
162
|
-
case "Stack":
|
|
163
|
-
return Stack.withMargin(l, margin);
|
|
164
|
-
case "Row":
|
|
165
|
-
return Row.withMargin(l, margin);
|
|
166
|
-
case "Elem":
|
|
167
|
-
return Elem.withMargin(l, margin);
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
exports.withMargin = withMargin;
|
|
171
|
-
function withAlignment(l, alignment) {
|
|
172
|
-
switch (l.tag) {
|
|
173
|
-
case "Stack":
|
|
174
|
-
return Stack.withAlignment(l, alignment);
|
|
175
|
-
case "Row":
|
|
176
|
-
return Row.withAlignment(l, alignment);
|
|
177
|
-
case "Elem":
|
|
178
|
-
return Elem.withAlignment(l, alignment);
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
exports.withAlignment = withAlignment;
|
|
182
|
-
function withWidth(l, width) {
|
|
183
|
-
switch (l.tag) {
|
|
184
|
-
case "Stack":
|
|
185
|
-
return Stack.withWidth(l, width);
|
|
186
|
-
case "Row":
|
|
187
|
-
return Row.withWidth(l, width);
|
|
188
|
-
case "Elem":
|
|
189
|
-
return Elem.withWidth(l, width);
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
exports.withWidth = withWidth;
|
|
193
161
|
function totalElementsWidth(l) {
|
|
194
162
|
switch (l.tag) {
|
|
195
163
|
case "Stack":
|
|
@@ -213,9 +181,8 @@ exports.isInstantiated = isInstantiated;
|
|
|
213
181
|
function instantiate(l, section, fields) {
|
|
214
182
|
switch (l.tag) {
|
|
215
183
|
case "Stack":
|
|
216
|
-
return Stack.withElements(l, l.elements.map(e => instantiate(e, section, fields)));
|
|
217
184
|
case "Row":
|
|
218
|
-
return
|
|
185
|
+
return (0, Utils_1.with_)(l, { elements: l.elements.map(e => instantiate(e, section, fields)) });
|
|
219
186
|
case "Elem":
|
|
220
187
|
return Elem.instantiate(l, section, fields);
|
|
221
188
|
}
|
|
@@ -266,10 +233,7 @@ function normalize(l, width, font_dict) {
|
|
|
266
233
|
const bounded_layout = boundWidth(scaled_layout, width);
|
|
267
234
|
console.debug("Widths are bounded. Filling fonts...");
|
|
268
235
|
const font_filled_layout = fillFonts(bounded_layout, font_dict);
|
|
269
|
-
console.debug("Fonts filled.
|
|
270
|
-
// const broken_layout = breakLines(font_filled_layout, font_dict);
|
|
271
|
-
console.debug("Lines broken.");
|
|
272
|
-
// return broken_layout;
|
|
236
|
+
console.debug("Fonts filled.");
|
|
273
237
|
return font_filled_layout;
|
|
274
238
|
}
|
|
275
239
|
exports.normalize = normalize;
|
|
@@ -286,7 +250,7 @@ function fillFonts(l, font_dict) {
|
|
|
286
250
|
const total_width = totalElementsWidth(l);
|
|
287
251
|
if (total_width <= Width.get_fixed_unchecked(l.width)) {
|
|
288
252
|
// throw `Cannot fill fonts of row with width ${JSON.stringify(this.width())} and total width ${total_width}`
|
|
289
|
-
return
|
|
253
|
+
return (0, Utils_1.with_)(l, { width: Width.absolute(total_width) });
|
|
290
254
|
}
|
|
291
255
|
}
|
|
292
256
|
return l;
|
|
@@ -296,47 +260,6 @@ function fillFonts(l, font_dict) {
|
|
|
296
260
|
}
|
|
297
261
|
}
|
|
298
262
|
exports.fillFonts = fillFonts;
|
|
299
|
-
function breakLines(l, font_dict) {
|
|
300
|
-
switch (l.tag) {
|
|
301
|
-
case "Stack": {
|
|
302
|
-
const stack = l;
|
|
303
|
-
return Stack.withElements(stack, stack.elements.map(e => breakLines(e, font_dict)));
|
|
304
|
-
}
|
|
305
|
-
case "Row": {
|
|
306
|
-
const row = l;
|
|
307
|
-
if (row.is_frozen) {
|
|
308
|
-
const total_width = row
|
|
309
|
-
.elements
|
|
310
|
-
.map(e => Width.get_fixed_unchecked(e.width))
|
|
311
|
-
.reduce((a, b) => a + b, 0.0);
|
|
312
|
-
if (total_width > Width.get_fixed_unchecked(row.width)) {
|
|
313
|
-
throw `Cannot break lines of frozen row with width ${row.width} and total width ${total_width}`;
|
|
314
|
-
}
|
|
315
|
-
else {
|
|
316
|
-
row.elements = row.elements.map(e => breakLines(e, font_dict));
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
else {
|
|
320
|
-
const lines = Row.breakLines(row, font_dict);
|
|
321
|
-
return Stack.stack(lines, row.margin, row.alignment, row.width, false);
|
|
322
|
-
}
|
|
323
|
-
return row;
|
|
324
|
-
}
|
|
325
|
-
case "Elem": {
|
|
326
|
-
if (isRef(l)) {
|
|
327
|
-
throw new Error("Cannot break lines of uninstantiated layout");
|
|
328
|
-
}
|
|
329
|
-
const elem = l;
|
|
330
|
-
const lines = Elem.break_lines(elem, font_dict);
|
|
331
|
-
// Make last line left if it's justified
|
|
332
|
-
if (lines[lines.length - 1].alignment === "Justified") {
|
|
333
|
-
lines[lines.length - 1] = withAlignment(lines[lines.length - 1], "Left");
|
|
334
|
-
}
|
|
335
|
-
return Stack.stack(lines, elem.margin, elem.alignment, elem.width, false);
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
exports.breakLines = breakLines;
|
|
340
263
|
function computeBoxes(l, font_dict) {
|
|
341
264
|
const top_left = new Point_1.Point(0.0, 0.0);
|
|
342
265
|
return computeTextboxPositions(l, top_left, font_dict).renderedLayout;
|
|
@@ -356,9 +279,10 @@ function computeTextboxPositions(l, top_left, font_dict) {
|
|
|
356
279
|
top_left = top_left.move_y_to(depth);
|
|
357
280
|
renderedElements.push(result.renderedLayout);
|
|
358
281
|
}
|
|
282
|
+
depth += stack.margin.bottom;
|
|
359
283
|
return {
|
|
360
284
|
depth, renderedLayout: {
|
|
361
|
-
...l, bounding_box: new Box_1.Box(originalTopLeft, top_left.move_x_by(Width.get_fixed_unchecked(stack.width))), elements: renderedElements
|
|
285
|
+
...l, bounding_box: new Box_1.Box(originalTopLeft, top_left.move_x_by(Width.get_fixed_unchecked(stack.width)).move_y_by(stack.margin.bottom)), elements: renderedElements
|
|
362
286
|
}
|
|
363
287
|
};
|
|
364
288
|
}
|
|
@@ -386,6 +310,7 @@ function computeTextboxPositions(l, top_left, font_dict) {
|
|
|
386
310
|
top_left.move_x_by(Width.get_fixed_unchecked(element.width) + per_elem_space);
|
|
387
311
|
renderedElements.push(result.renderedLayout);
|
|
388
312
|
}
|
|
313
|
+
depth += row.margin.bottom;
|
|
389
314
|
return {
|
|
390
315
|
depth, renderedLayout: {
|
|
391
316
|
...l, bounding_box: new Box_1.Box(originalTopLeft, originalTopLeft.move_y_by(depth).move_x_by(Width.get_fixed_unchecked(row.width))), elements: renderedElements
|
|
@@ -398,7 +323,6 @@ function computeTextboxPositions(l, top_left, font_dict) {
|
|
|
398
323
|
throw new Error("Cannot compute textbox positions of uninstantiated layout");
|
|
399
324
|
}
|
|
400
325
|
const height = Font.get_height(elem.font, font_dict);
|
|
401
|
-
const width = Width.get_fixed_unchecked(elem.text_width);
|
|
402
326
|
top_left = top_left.move_y_by(elem.margin.top).move_x_by(elem.margin.left);
|
|
403
327
|
let line = 1;
|
|
404
328
|
let cursor = top_left.x;
|
|
@@ -411,16 +335,36 @@ function computeTextboxPositions(l, top_left, font_dict) {
|
|
|
411
335
|
span.line = line;
|
|
412
336
|
cursor += span.width;
|
|
413
337
|
});
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
338
|
+
const lineWidths = elem.spans.reduce((acc, span) => {
|
|
339
|
+
acc[span.line - 1].width += span.width;
|
|
340
|
+
return acc;
|
|
341
|
+
}, Array.from({ length: line }, (_, i) => ({ line: i + 1, width: 0 })));
|
|
342
|
+
switch (elem.alignment) {
|
|
343
|
+
case "Center":
|
|
344
|
+
elem.spans.forEach(span => {
|
|
345
|
+
span.bbox = span.bbox.move_x_by((Width.get_fixed_unchecked(elem.width) - lineWidths[span.line - 1].width) / 2.0);
|
|
346
|
+
});
|
|
347
|
+
break;
|
|
348
|
+
case "Right":
|
|
349
|
+
elem.spans.forEach(span => {
|
|
350
|
+
span.bbox = span.bbox.move_x_by(Width.get_fixed_unchecked(elem.width) - lineWidths[span.line - 1].width);
|
|
351
|
+
});
|
|
352
|
+
break;
|
|
353
|
+
case "Justified": {
|
|
354
|
+
for (let i = 1; i < line; i++) {
|
|
355
|
+
const lineSpans = elem.spans.filter(span => span.line === i && span.text !== "\n\n" && span.text !== "\n" && span.text !== " ");
|
|
356
|
+
const totalWidth = lineSpans.reduce((acc, span) => acc + span.width, 0);
|
|
357
|
+
const perSpace = (Width.get_fixed_unchecked(elem.width) - totalWidth) / (lineSpans.length - 1);
|
|
358
|
+
let cursor = 0;
|
|
359
|
+
lineSpans.forEach(span => {
|
|
360
|
+
span.bbox = span.bbox.move_x_by(cursor - span.bbox.top_left.x);
|
|
361
|
+
cursor += span.width + perSpace;
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
const textbox = new Box_1.Box(top_left, top_left.move_x_by(Width.get_fixed_unchecked(elem.width)).move_y_by(height * line + elem.margin.bottom));
|
|
367
|
+
return { depth: top_left.y + height * line + elem.margin.bottom, renderedLayout: { ...l, bounding_box: textbox } };
|
|
424
368
|
}
|
|
425
369
|
}
|
|
426
370
|
}
|
package/dist/PdfLayout.d.ts
CHANGED
|
@@ -22,5 +22,13 @@ export type RenderProps = {
|
|
|
22
22
|
debug: boolean;
|
|
23
23
|
};
|
|
24
24
|
export declare const render: ({ resume_name, resume, data_schemas, layout_schemas, resume_layout, storage, fontDict }: RenderProps) => Promise<RenderResult>;
|
|
25
|
+
type Tracker = {
|
|
26
|
+
page: number;
|
|
27
|
+
pageContainer: PDFKit.PDFDocument;
|
|
28
|
+
height: number;
|
|
29
|
+
layout: ResumeLayout;
|
|
30
|
+
fontDict: FontDict;
|
|
31
|
+
};
|
|
25
32
|
export declare const mergeSpans: (spans: Elem.Span[]) => Elem.Span[];
|
|
26
|
-
export declare const renderSectionLayout: (layout: Layout.RenderedLayout,
|
|
33
|
+
export declare const renderSectionLayout: (layout: Layout.RenderedLayout, tracker: Tracker) => void;
|
|
34
|
+
export {};
|
package/dist/PdfLayout.js
CHANGED
|
@@ -34,7 +34,6 @@ const render = async ({ resume_name, resume, data_schemas, layout_schemas, resum
|
|
|
34
34
|
let end_time = Date.now();
|
|
35
35
|
console.info(`Loading time: ${end_time - start_time}ms`);
|
|
36
36
|
const doc = new pdfkit_1.default();
|
|
37
|
-
// doc.pipe(fs.createWriteStream('output.pdf'));
|
|
38
37
|
const stream = doc.pipe((0, blob_stream_1.default)());
|
|
39
38
|
start_time = Date.now();
|
|
40
39
|
const layouts = await (0, AnyLayout_1.render)({ layout_schemas, resume, data_schemas, resume_layout, storage, fontDict });
|
|
@@ -56,19 +55,16 @@ const render = async ({ resume_name, resume, data_schemas, layout_schemas, resum
|
|
|
56
55
|
console.error(e);
|
|
57
56
|
}
|
|
58
57
|
console.log("Rendering the document...");
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
doc.moveTo(i, 0).lineTo(i, resume_layout.height).stroke();
|
|
67
|
-
}
|
|
68
|
-
doc.strokeColor("black");
|
|
58
|
+
const tracker = {
|
|
59
|
+
page: 0,
|
|
60
|
+
pageContainer: doc,
|
|
61
|
+
height: 0,
|
|
62
|
+
layout: resume_layout,
|
|
63
|
+
fontDict: fontDict,
|
|
64
|
+
};
|
|
69
65
|
for (const layout of layouts) {
|
|
70
|
-
(0, exports.renderSectionLayout)(layout,
|
|
71
|
-
|
|
66
|
+
(0, exports.renderSectionLayout)(layout, tracker);
|
|
67
|
+
tracker.height += layout.bounding_box.height() + layout.margin.top + layout.margin.bottom;
|
|
72
68
|
}
|
|
73
69
|
console.log("Rendering is completed. Saving the document...");
|
|
74
70
|
console.log("Document is saved to output.pdf");
|
|
@@ -83,6 +79,15 @@ const render = async ({ resume_name, resume, data_schemas, layout_schemas, resum
|
|
|
83
79
|
});
|
|
84
80
|
};
|
|
85
81
|
exports.render = render;
|
|
82
|
+
const getPageContainer = (page, tracker) => {
|
|
83
|
+
if (page > tracker.page) {
|
|
84
|
+
tracker.page = page;
|
|
85
|
+
tracker.pageContainer.addPage({
|
|
86
|
+
size: [tracker.layout.width, tracker.layout.height],
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
return tracker.pageContainer;
|
|
90
|
+
};
|
|
86
91
|
const mergeSpans = (spans) => {
|
|
87
92
|
const merged_spans = [];
|
|
88
93
|
let currentSpan = spans[0];
|
|
@@ -104,49 +109,52 @@ const mergeSpans = (spans) => {
|
|
|
104
109
|
return merged_spans;
|
|
105
110
|
};
|
|
106
111
|
exports.mergeSpans = mergeSpans;
|
|
107
|
-
const renderSectionLayout = (layout,
|
|
112
|
+
const renderSectionLayout = (layout, tracker) => {
|
|
108
113
|
switch (layout.tag) {
|
|
109
114
|
case "Stack": {
|
|
110
115
|
const stack = layout;
|
|
111
116
|
for (const elem of stack.elements) {
|
|
112
|
-
(0, exports.renderSectionLayout)(elem,
|
|
117
|
+
(0, exports.renderSectionLayout)(elem, tracker);
|
|
113
118
|
}
|
|
114
119
|
break;
|
|
115
120
|
}
|
|
116
121
|
case "Row": {
|
|
117
122
|
const row = layout;
|
|
118
123
|
for (const elem of row.elements) {
|
|
119
|
-
(0, exports.renderSectionLayout)(elem,
|
|
124
|
+
(0, exports.renderSectionLayout)(elem, tracker);
|
|
120
125
|
}
|
|
121
126
|
break;
|
|
122
127
|
}
|
|
123
128
|
case "Elem": {
|
|
124
129
|
const elem = layout;
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
130
|
+
if (!layout.bounding_box) {
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
const spans = elem.alignment === "Justified" ? elem.spans : (0, exports.mergeSpans)(elem.spans);
|
|
134
|
+
spans.forEach((span) => {
|
|
135
|
+
if (span.text === "" || span.text === " " || span.text === "\n" || span.text === "\n\n") {
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
const absoluteY = layout.bounding_box.top_left.y + tracker.height + span.bbox.top_left.y;
|
|
139
|
+
const page = Math.floor(absoluteY / (tracker.layout.height - tracker.layout.margin.top - tracker.layout.margin.bottom));
|
|
140
|
+
const currentPageY = absoluteY % (tracker.layout.height - tracker.layout.margin.top - tracker.layout.margin.bottom);
|
|
141
|
+
const y = currentPageY + tracker.layout.margin.top;
|
|
142
|
+
const x = layout.bounding_box.top_left.x + tracker.layout.margin.left + span.bbox.top_left.x;
|
|
143
|
+
tracker.pageContainer = getPageContainer(page, tracker);
|
|
144
|
+
tracker.pageContainer.
|
|
128
145
|
font(_1.Font.full_name(span.font)).
|
|
129
146
|
fontSize(span.font.size).
|
|
130
|
-
text(span.text,
|
|
131
|
-
+ resume_layout.margin.left
|
|
132
|
-
+ span.bbox.top_left.x, layout.bounding_box.top_left.y
|
|
133
|
-
+ resume_layout.margin.top
|
|
134
|
-
+ current_height
|
|
135
|
-
+ span.bbox.top_left.y, { lineBreak: false });
|
|
147
|
+
text(span.text, x, y, { lineBreak: false });
|
|
136
148
|
if (span.is_code) {
|
|
137
149
|
// Add a rounded rectangle around the code
|
|
138
|
-
|
|
150
|
+
tracker.pageContainer.roundedRect(layout.bounding_box.top_left.x + tracker.layout.margin.left + span.bbox.top_left.x - span.font.size / 5, layout.bounding_box.top_left.y + tracker.layout.margin.top + tracker.height + span.bbox.top_left.y, span.bbox.width() + span.font.size / 5 * 2, span.bbox.height(), 5).stroke();
|
|
139
151
|
// Add a background color to the code
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
152
|
+
tracker.pageContainer.fillColor("black");
|
|
153
|
+
tracker.pageContainer.fillOpacity(0.05);
|
|
154
|
+
tracker.pageContainer.rect(layout.bounding_box.top_left.x + tracker.layout.margin.left + span.bbox.top_left.x - span.font.size / 5, layout.bounding_box.top_left.y + tracker.layout.margin.top + tracker.height + span.bbox.top_left.y, span.bbox.width() + span.font.size / 5 * 2, span.bbox.height()).fill();
|
|
155
|
+
tracker.pageContainer.fillOpacity(1);
|
|
144
156
|
}
|
|
145
157
|
});
|
|
146
|
-
// doc.
|
|
147
|
-
// font(Font.full_name(elem.font)).
|
|
148
|
-
// fontSize(elem.font.size).
|
|
149
|
-
// text(elem.item, layout.bounding_box.top_left.x + resume_layout.margin.left, layout.bounding_box.top_left.y + resume_layout.margin.top + current_height, { lineBreak: false });
|
|
150
158
|
break;
|
|
151
159
|
}
|
|
152
160
|
}
|
package/dist/Row.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Alignment, Margin, Width } from ".";
|
|
2
|
-
import { FontDict } from "./AnyLayout";
|
|
3
2
|
import { Optional } from "./Utils";
|
|
4
3
|
import * as Layout from "./Layout";
|
|
5
4
|
export type t = {
|
|
@@ -14,16 +13,8 @@ export type t = {
|
|
|
14
13
|
type Row = t;
|
|
15
14
|
export declare function from(w: Optional<Row>): Row;
|
|
16
15
|
export declare function row(elements: Layout.t[], margin: Margin.t, alignment: Alignment.t, width: Width.t, is_frozen: boolean, is_fill: boolean): Row;
|
|
17
|
-
export declare function copy(r: Row): Row;
|
|
18
16
|
export declare function default_(): Row;
|
|
19
|
-
export declare function withElements(r: Row, elements: Layout.t[]): Row;
|
|
20
|
-
export declare function withMargin(r: Row, margin: Margin.t): Row;
|
|
21
|
-
export declare function withAlignment(r: Row, alignment: Alignment.t): Row;
|
|
22
|
-
export declare function withWidth(r: Row, width: Width.t): Row;
|
|
23
|
-
export declare function withFrozen(r: Row, is_frozen: boolean): Row;
|
|
24
|
-
export declare function withFill(r: Row, is_fill: boolean): Row;
|
|
25
17
|
export declare function elementsWidth(r: Row): number;
|
|
26
18
|
export declare function boundWidth(r: Row, width: number): Row;
|
|
27
19
|
export declare function scaleWidth(r: Row, w: number): Row;
|
|
28
|
-
export declare function breakLines(r: Row, font_dict: FontDict): Row[];
|
|
29
20
|
export {};
|
package/dist/Row.js
CHANGED
|
@@ -23,8 +23,9 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
23
23
|
return result;
|
|
24
24
|
};
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
exports.
|
|
26
|
+
exports.scaleWidth = exports.boundWidth = exports.elementsWidth = exports.default_ = exports.row = exports.from = void 0;
|
|
27
27
|
const _1 = require(".");
|
|
28
|
+
const Utils_1 = require("./Utils");
|
|
28
29
|
const Layout = __importStar(require("./Layout"));
|
|
29
30
|
function from(w) {
|
|
30
31
|
return { ...default_(), ...w };
|
|
@@ -42,12 +43,6 @@ function row(elements, margin, alignment, width, is_frozen, is_fill) {
|
|
|
42
43
|
};
|
|
43
44
|
}
|
|
44
45
|
exports.row = row;
|
|
45
|
-
function copy(r) {
|
|
46
|
-
return {
|
|
47
|
-
...r,
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
exports.copy = copy;
|
|
51
46
|
function default_() {
|
|
52
47
|
return {
|
|
53
48
|
tag: "Row",
|
|
@@ -60,48 +55,6 @@ function default_() {
|
|
|
60
55
|
};
|
|
61
56
|
}
|
|
62
57
|
exports.default_ = default_;
|
|
63
|
-
function withElements(r, elements) {
|
|
64
|
-
return {
|
|
65
|
-
...r,
|
|
66
|
-
elements,
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
exports.withElements = withElements;
|
|
70
|
-
function withMargin(r, margin) {
|
|
71
|
-
return {
|
|
72
|
-
...r,
|
|
73
|
-
margin,
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
exports.withMargin = withMargin;
|
|
77
|
-
function withAlignment(r, alignment) {
|
|
78
|
-
return {
|
|
79
|
-
...r,
|
|
80
|
-
alignment,
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
exports.withAlignment = withAlignment;
|
|
84
|
-
function withWidth(r, width) {
|
|
85
|
-
return {
|
|
86
|
-
...r,
|
|
87
|
-
width,
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
exports.withWidth = withWidth;
|
|
91
|
-
function withFrozen(r, is_frozen) {
|
|
92
|
-
return {
|
|
93
|
-
...r,
|
|
94
|
-
is_frozen,
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
exports.withFrozen = withFrozen;
|
|
98
|
-
function withFill(r, is_fill) {
|
|
99
|
-
return {
|
|
100
|
-
...r,
|
|
101
|
-
is_fill,
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
exports.withFill = withFill;
|
|
105
58
|
function elementsWidth(r) {
|
|
106
59
|
return r.elements.map(e => _1.Width.get_fixed_unchecked(e.width)).reduce((a, b) => a + b, 0.0);
|
|
107
60
|
}
|
|
@@ -117,29 +70,9 @@ function boundWidth(r, width) {
|
|
|
117
70
|
}
|
|
118
71
|
exports.boundWidth = boundWidth;
|
|
119
72
|
function scaleWidth(r, w) {
|
|
120
|
-
return
|
|
73
|
+
return (0, Utils_1.with_)(r, {
|
|
74
|
+
elements: r.elements.map(e => Layout.scaleWidth(e, w)),
|
|
75
|
+
width: _1.Width.scale(r.width, w)
|
|
76
|
+
});
|
|
121
77
|
}
|
|
122
78
|
exports.scaleWidth = scaleWidth;
|
|
123
|
-
function breakLines(r, font_dict) {
|
|
124
|
-
const lines = [];
|
|
125
|
-
let current_line = [];
|
|
126
|
-
let current_width = 0.0;
|
|
127
|
-
const elements = r
|
|
128
|
-
.elements
|
|
129
|
-
.map(e => Layout.breakLines(e, font_dict));
|
|
130
|
-
for (const element of elements) {
|
|
131
|
-
const element_width = _1.Width.get_fixed_unchecked(element.width);
|
|
132
|
-
if (current_width + element_width > _1.Width.get_fixed_unchecked(r.width)) {
|
|
133
|
-
lines.push(withElements(r, current_line));
|
|
134
|
-
current_line = [];
|
|
135
|
-
current_width = 0.0;
|
|
136
|
-
}
|
|
137
|
-
current_line.push(element);
|
|
138
|
-
current_width += element_width;
|
|
139
|
-
}
|
|
140
|
-
if (current_line.length > 0) {
|
|
141
|
-
lines.push(withElements(r, current_line));
|
|
142
|
-
}
|
|
143
|
-
return lines;
|
|
144
|
-
}
|
|
145
|
-
exports.breakLines = breakLines;
|
package/dist/Stack.d.ts
CHANGED
|
@@ -11,13 +11,7 @@ export type t = {
|
|
|
11
11
|
type Stack = t;
|
|
12
12
|
export declare function from(w: Optional<Stack>): Stack;
|
|
13
13
|
export declare function stack(elements: Layout.t[], margin: Margin.t, alignment: Alignment.t, width: Width.t, is_fill: boolean): Stack;
|
|
14
|
-
export declare function copy(s: Stack): Stack;
|
|
15
14
|
export declare function default_(): Stack;
|
|
16
|
-
export declare function withElements(s: Stack, elements: Layout.t[]): Stack;
|
|
17
|
-
export declare function withMargin(s: Stack, margin: Margin.t): Stack;
|
|
18
|
-
export declare function withAlignment(s: Stack, alignment: Alignment.t): Stack;
|
|
19
|
-
export declare function withWidth(s: Stack, width: Width.t): Stack;
|
|
20
|
-
export declare function withIsFill(s: Stack, is_fill: boolean): Stack;
|
|
21
15
|
export declare function boundWidth(s: Stack, width: number): Stack;
|
|
22
16
|
export declare function scaleWidth(s: Stack, scale: number): Stack;
|
|
23
17
|
export {};
|
package/dist/Stack.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.scaleWidth = exports.boundWidth = exports.
|
|
3
|
+
exports.scaleWidth = exports.boundWidth = exports.default_ = exports.stack = exports.from = void 0;
|
|
4
4
|
const _1 = require(".");
|
|
5
|
+
const Utils_1 = require("./Utils");
|
|
5
6
|
function from(w) {
|
|
6
7
|
return { ...default_(), ...w };
|
|
7
8
|
}
|
|
@@ -17,12 +18,6 @@ function stack(elements, margin, alignment, width, is_fill) {
|
|
|
17
18
|
};
|
|
18
19
|
}
|
|
19
20
|
exports.stack = stack;
|
|
20
|
-
function copy(s) {
|
|
21
|
-
return {
|
|
22
|
-
...s,
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
exports.copy = copy;
|
|
26
21
|
function default_() {
|
|
27
22
|
return {
|
|
28
23
|
tag: "Stack",
|
|
@@ -34,41 +29,6 @@ function default_() {
|
|
|
34
29
|
};
|
|
35
30
|
}
|
|
36
31
|
exports.default_ = default_;
|
|
37
|
-
function withElements(s, elements) {
|
|
38
|
-
return {
|
|
39
|
-
...s,
|
|
40
|
-
elements,
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
exports.withElements = withElements;
|
|
44
|
-
function withMargin(s, margin) {
|
|
45
|
-
return {
|
|
46
|
-
...s,
|
|
47
|
-
margin,
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
exports.withMargin = withMargin;
|
|
51
|
-
function withAlignment(s, alignment) {
|
|
52
|
-
return {
|
|
53
|
-
...s,
|
|
54
|
-
alignment,
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
exports.withAlignment = withAlignment;
|
|
58
|
-
function withWidth(s, width) {
|
|
59
|
-
return {
|
|
60
|
-
...s,
|
|
61
|
-
width,
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
exports.withWidth = withWidth;
|
|
65
|
-
function withIsFill(s, is_fill) {
|
|
66
|
-
return {
|
|
67
|
-
...s,
|
|
68
|
-
is_fill,
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
exports.withIsFill = withIsFill;
|
|
72
32
|
function boundWidth(s, width) {
|
|
73
33
|
const bound = s.width.tag === "Absolute" ? Math.min(s.width.value, width)
|
|
74
34
|
: s.width.tag === "Fill" ? width
|
|
@@ -76,10 +36,10 @@ function boundWidth(s, width) {
|
|
|
76
36
|
if (bound === null) {
|
|
77
37
|
throw new Error("Cannot bound width of non-unitized widths!");
|
|
78
38
|
}
|
|
79
|
-
return
|
|
39
|
+
return (0, Utils_1.with_)(s, { elements: s.elements.map(e => _1.Layout.boundWidth(e, bound)), width: _1.Width.absolute(bound) });
|
|
80
40
|
}
|
|
81
41
|
exports.boundWidth = boundWidth;
|
|
82
42
|
function scaleWidth(s, scale) {
|
|
83
|
-
return
|
|
43
|
+
return (0, Utils_1.with_)(s, { elements: s.elements.map(e => _1.Layout.scaleWidth(e, scale)), width: _1.Width.scale(s.width, scale) });
|
|
84
44
|
}
|
|
85
45
|
exports.scaleWidth = scaleWidth;
|
package/dist/Utils.d.ts
CHANGED
package/dist/Utils.js
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.copy = exports.with_ = void 0;
|
|
4
4
|
function with_(e, w) {
|
|
5
5
|
return { ...e, ...w };
|
|
6
6
|
}
|
|
7
7
|
exports.with_ = with_;
|
|
8
|
-
|
|
8
|
+
function copy(s) {
|
|
9
|
+
return {
|
|
10
|
+
...s,
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
exports.copy = copy;
|