abstract-document 16.0.39 → 16.1.0
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 +2 -1
- package/lib/abstract-document/markdown/markdown.d.ts.map +1 -1
- package/lib/abstract-document/markdown/markdown.js +1 -10
- package/lib/abstract-document/markdown/markdown.js.map +1 -1
- package/lib/abstract-document/section-elements/paragraph.d.ts +0 -2
- package/lib/abstract-document/section-elements/paragraph.d.ts.map +1 -1
- package/lib/abstract-document/section-elements/paragraph.js +1 -2
- package/lib/abstract-document/section-elements/paragraph.js.map +1 -1
- package/lib/abstract-document/styles/text-style.d.ts +0 -3
- package/lib/abstract-document/styles/text-style.d.ts.map +1 -1
- package/lib/abstract-document/styles/text-style.js +0 -1
- package/lib/abstract-document/styles/text-style.js.map +1 -1
- package/lib/abstract-document-exporters/pdf/measure.js +13 -3
- package/lib/abstract-document-exporters/pdf/measure.js.map +1 -1
- package/lib/abstract-document-exporters/pdf/pre-process.js +23 -1
- package/lib/abstract-document-exporters/pdf/pre-process.js.map +1 -1
- package/lib/abstract-document-exporters/pdf/render.d.ts.map +1 -1
- package/lib/abstract-document-exporters/pdf/render.js +116 -152
- package/lib/abstract-document-exporters/pdf/render.js.map +1 -1
- package/lib/abstract-document-exporters/pdf/textRunRow.d.ts +8 -0
- package/lib/abstract-document-exporters/pdf/textRunRow.d.ts.map +1 -0
- package/lib/abstract-document-exporters/pdf/textRunRow.js +225 -0
- package/lib/abstract-document-exporters/pdf/textRunRow.js.map +1 -0
- package/lib/abstract-document-xml/xsd-template/styles.d.ts +2 -2
- package/lib/abstract-document-xml/xsd-template/styles.d.ts.map +1 -1
- package/lib/abstract-document-xml/xsd-template/styles.js +4 -14
- package/lib/abstract-document-xml/xsd-template/styles.js.map +1 -1
- package/lib/abstract-document-xml/xsd-template/xsd-template.d.ts +2 -2
- package/lib/abstract-document-xml/xsd-template/xsd-template.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/abstract-document/markdown/markdown.ts +1 -11
- package/src/abstract-document/section-elements/paragraph.ts +1 -4
- package/src/abstract-document/styles/text-style.ts +0 -4
- package/src/abstract-document-exporters/pdf/measure.ts +15 -3
- package/src/abstract-document-exporters/pdf/pre-process.ts +22 -1
- package/src/abstract-document-exporters/pdf/render.ts +93 -172
- package/src/abstract-document-exporters/pdf/textRunRow.ts +222 -0
- package/src/abstract-document-xml/xsd-template/styles.ts +4 -14
- package/lib/abstract-document-exporters/shared/to-base-64.d.ts +0 -3
- package/lib/abstract-document-exporters/shared/to-base-64.d.ts.map +0 -1
- package/lib/abstract-document-exporters/shared/to-base-64.js +0 -19
- package/lib/abstract-document-exporters/shared/to-base-64.js.map +0 -1
|
@@ -5,6 +5,7 @@ import { paginate, Page, getHeaderAndFooter } from "./paginate.js";
|
|
|
5
5
|
import { updatePageRefs } from "./update-refs.js";
|
|
6
6
|
import { renderImage } from "./render-image.js";
|
|
7
7
|
import { registerFonts, getFontNameStyle } from "./font.js";
|
|
8
|
+
import { PdfKitAlignment, rowsCombineTextRuns, rowsSplit } from "./textRunRow.js";
|
|
8
9
|
|
|
9
10
|
export type PdfExportOptions = {
|
|
10
11
|
compress: boolean;
|
|
@@ -280,21 +281,20 @@ function renderParagraph(
|
|
|
280
281
|
rows.push(currentRow);
|
|
281
282
|
}
|
|
282
283
|
|
|
283
|
-
//if the paragraph is markdown, we need to render it separately
|
|
284
|
-
//since alignment is different for that
|
|
285
|
-
if(paragraph.isMarkdown !== undefined && paragraph.isMarkdown) {
|
|
286
|
-
renderMarkdownRows(rows, resources, pdfKit, desiredSizes, finalRect, style, availableWidth);
|
|
287
|
-
return;
|
|
288
|
-
}
|
|
289
|
-
|
|
290
284
|
let y = finalRect.y + style.margins.top;
|
|
291
|
-
|
|
285
|
+
const alignment = parseAlignment(style.alignment);
|
|
286
|
+
const newRows = rowsSplit(rows, availableWidth, desiredSizes, alignment);
|
|
287
|
+
const { newDesiredSizes, combinedRows } = rowsCombineTextRuns(resources, pdfKit, newRows, desiredSizes, alignment, style.textStyle);
|
|
288
|
+
for (let r = 0; r < combinedRows.length; r++) {
|
|
289
|
+
const row = combinedRows[r];
|
|
290
|
+
const isLast = r === combinedRows.length - 1;
|
|
292
291
|
if (row.length === 0) {
|
|
293
292
|
continue;
|
|
294
293
|
}
|
|
295
294
|
|
|
296
|
-
const rowWidth = row.reduce((a, b) => a + getDesiredSize(b,
|
|
295
|
+
const rowWidth = row.reduce((a, b) => a + getDesiredSize(b, newDesiredSizes).width, 0);
|
|
297
296
|
const remainingWidth = availableWidth - rowWidth;
|
|
297
|
+
const justificationWidth = !isLast && row.length > 1 ? remainingWidth / (row.length - 1) : 0;
|
|
298
298
|
let x = finalRect.x;
|
|
299
299
|
|
|
300
300
|
if (style.alignment === "Start" || style.alignment === "Justify") {
|
|
@@ -303,11 +303,13 @@ function renderParagraph(
|
|
|
303
303
|
x -= style.margins.right;
|
|
304
304
|
}
|
|
305
305
|
|
|
306
|
-
if (row.length > 1 || row[0].type === "Image") {
|
|
306
|
+
if (row.length > 1 || row[0].type === "Image" || row[0].type === "TextRun") {
|
|
307
307
|
// Using continued with alignment "center" or "right" is broken:
|
|
308
308
|
// https://github.com/foliojs/pdfkit/issues/240
|
|
309
309
|
// Therefore we have to position it ourself
|
|
310
|
-
// NOTE:
|
|
310
|
+
// NOTE: Texts with multiple atoms with width over the available width are not supported.
|
|
311
|
+
// NOTE2: This should be fixed now since we split the text into an array of words instead
|
|
312
|
+
// and place them manually here
|
|
311
313
|
if (style.alignment === "Center") {
|
|
312
314
|
x += 0.5 * remainingWidth;
|
|
313
315
|
} else if (style.alignment === "End") {
|
|
@@ -318,167 +320,27 @@ function renderParagraph(
|
|
|
318
320
|
let rowHeight = 0;
|
|
319
321
|
const lastIndex = row[row.length - 1]?.type === "LineBreak" ? row.length - 2 : row.length - 1;
|
|
320
322
|
for (const [i, atom] of row.entries()) {
|
|
321
|
-
const atomSize = getDesiredSize(atom,
|
|
323
|
+
const atomSize = getDesiredSize(atom, newDesiredSizes);
|
|
322
324
|
renderAtom(
|
|
323
325
|
resources,
|
|
324
326
|
pdfKit,
|
|
325
327
|
AD.Rect.create(x, y, atomSize.width, atomSize.height),
|
|
326
328
|
style.textStyle,
|
|
327
329
|
atom,
|
|
328
|
-
parseAlignment(style.alignment),
|
|
329
|
-
availableWidth,
|
|
330
|
-
i === 0,
|
|
331
|
-
i === lastIndex
|
|
332
|
-
);
|
|
333
|
-
x += atomSize.width;
|
|
334
|
-
rowHeight = Math.max(rowHeight, atomSize.height);
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
y += rowHeight;
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
function renderMarkdownRows(
|
|
342
|
-
rawRows: ReadonlyArray<ReadonlyArray<AD.Atom.Atom>>,
|
|
343
|
-
resources: AD.Resources.Resources,
|
|
344
|
-
pdfKit: PDFKit.PDFDocument,
|
|
345
|
-
desiredSizes: Map<{}, AD.Size.Size>,
|
|
346
|
-
finalRect: AD.Rect.Rect,
|
|
347
|
-
paragraphStyle: AD.ParagraphStyle.ParagraphStyle,
|
|
348
|
-
availableWidth: number,
|
|
349
|
-
): void {
|
|
350
|
-
const rows = splitRows(rawRows, availableWidth, desiredSizes);
|
|
351
|
-
let y = finalRect.y + paragraphStyle.margins.top;
|
|
352
|
-
let markdownTextStyle: AD.TextStyle.TextStyle | undefined = undefined;
|
|
353
|
-
for(const row of rows) {
|
|
354
|
-
for(const atom of row) {
|
|
355
|
-
if(atom.type === "TextRun") {
|
|
356
|
-
markdownTextStyle = AD.Resources.getNestedStyle(
|
|
357
|
-
paragraphStyle.textStyle,
|
|
358
|
-
atom.style,
|
|
359
|
-
"TextStyle",
|
|
360
|
-
atom.styleName,
|
|
361
|
-
resources,
|
|
362
|
-
atom.nestedStyleNames || []
|
|
363
|
-
) as AD.TextStyle.TextStyle;
|
|
364
|
-
break;
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
const defaultStyle = parseAlignment(paragraphStyle.alignment);
|
|
370
|
-
const alignment = markdownTextStyle?.alignment ?? defaultStyle;
|
|
371
|
-
for (let row of rows) {
|
|
372
|
-
if (row.length === 0) {
|
|
373
|
-
continue;
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
const rowWidth = row.reduce((a, b) => a + getDesiredSize(b, desiredSizes).width, 0);
|
|
377
|
-
const remainingWidth = availableWidth - rowWidth;
|
|
378
|
-
const justificationWidth = row.length > 1 ? remainingWidth / (row.length - 1) : 0;
|
|
379
|
-
let x = finalRect.x;
|
|
380
|
-
|
|
381
|
-
if (alignment === "left" || alignment === "justify") {
|
|
382
|
-
x += paragraphStyle.margins.left;
|
|
383
|
-
} else if (alignment === "right") {
|
|
384
|
-
x -= paragraphStyle.margins.right;
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
if (row.length > 1 || row[0].type === "Image") {
|
|
388
|
-
if (alignment === "center") {
|
|
389
|
-
x += 0.5 * remainingWidth;
|
|
390
|
-
} else if (alignment === "right") {
|
|
391
|
-
x += remainingWidth;
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
let rowHeight = 0;
|
|
396
|
-
const lastIndex = row[row.length - 1]?.type === "LineBreak" ? row.length - 2 : row.length - 1;
|
|
397
|
-
for (const [i, atom] of row.entries()) {
|
|
398
|
-
const atomSize = getDesiredSize(atom, desiredSizes);
|
|
399
|
-
renderAtom(
|
|
400
|
-
resources,
|
|
401
|
-
pdfKit,
|
|
402
|
-
AD.Rect.create(x, y, atomSize.width, atomSize.height),
|
|
403
|
-
paragraphStyle.textStyle,
|
|
404
|
-
atom,
|
|
405
330
|
alignment,
|
|
406
331
|
availableWidth,
|
|
407
332
|
i === 0,
|
|
408
333
|
i === lastIndex
|
|
409
334
|
);
|
|
410
|
-
x += atomSize.width + (alignment === "
|
|
335
|
+
x += atomSize.width + (style.alignment === "Justify" ? justificationWidth : 0);
|
|
411
336
|
rowHeight = Math.max(rowHeight, atomSize.height);
|
|
412
337
|
}
|
|
413
|
-
y += rowHeight;
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
function splitRows(rows: ReadonlyArray<ReadonlyArray<AD.Atom.Atom>>, availableWidth: number, desiredSizes: Map<{}, AD.Size.Size>): ReadonlyArray<ReadonlyArray<AD.Atom.Atom>> {
|
|
418
|
-
const newRows: Array<ReadonlyArray<AD.Atom.Atom>> = [];
|
|
419
|
-
|
|
420
|
-
for(const row of rows) {
|
|
421
|
-
if(row.length <= 1) {
|
|
422
|
-
newRows.push(row);
|
|
423
|
-
continue;
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
const width = row.reduce((a, b) => a + getDesiredSize(b, desiredSizes).width, 0);
|
|
427
|
-
if(width <= availableWidth) {
|
|
428
|
-
newRows.push(row);
|
|
429
|
-
continue;
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
//we need to split it, because it doesn't fit
|
|
433
|
-
let currentRow: Array<AD.Atom.Atom> = [];
|
|
434
|
-
let currentWidth = 0;
|
|
435
|
-
let lastWasSpace = false;
|
|
436
|
-
|
|
437
|
-
for(let i = 0; i < row.length; i++) {
|
|
438
|
-
const atom = row[i];
|
|
439
|
-
if(atom.type !== "TextRun") {
|
|
440
|
-
continue;
|
|
441
|
-
}
|
|
442
338
|
|
|
443
|
-
|
|
444
|
-
if(atom.type !== "TextRun") {
|
|
445
|
-
currentRow.push(atom);
|
|
446
|
-
currentWidth += width;
|
|
447
|
-
continue;
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
const isSpace = atom.text.replaceAll(/[\p{Zs}]/ug, "").length === 0;
|
|
451
|
-
const lastSpace = lastWasSpace;
|
|
452
|
-
lastWasSpace = isSpace;
|
|
453
|
-
|
|
454
|
-
if(isSpace && currentWidth === 0 && i !== 0) {
|
|
455
|
-
continue;
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
if(currentWidth + width <= availableWidth) {
|
|
459
|
-
currentRow.push(atom);
|
|
460
|
-
currentWidth += width;
|
|
461
|
-
continue;
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
//was it a space??
|
|
465
|
-
if(isSpace) {
|
|
466
|
-
newRows.push(currentRow);
|
|
467
|
-
currentRow = [];
|
|
468
|
-
currentWidth = 0;
|
|
469
|
-
continue;
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
newRows.push(lastSpace ? currentRow.slice(0, -1) : currentRow);
|
|
473
|
-
currentRow = [atom];
|
|
474
|
-
currentWidth = width;
|
|
475
|
-
}
|
|
476
|
-
newRows.push(lastWasSpace ? currentRow.slice(0, -1) : currentRow);
|
|
339
|
+
y += rowHeight;
|
|
477
340
|
}
|
|
478
|
-
return newRows;
|
|
479
341
|
}
|
|
480
342
|
|
|
481
|
-
function parseAlignment(paragraphAlignment: AD.ParagraphStyle.TextAlignment | undefined):
|
|
343
|
+
function parseAlignment(paragraphAlignment: AD.ParagraphStyle.TextAlignment | undefined): PdfKitAlignment {
|
|
482
344
|
switch (paragraphAlignment) {
|
|
483
345
|
case "Start":
|
|
484
346
|
return "left";
|
|
@@ -499,7 +361,7 @@ function renderAtom(
|
|
|
499
361
|
finalRect: AD.Rect.Rect,
|
|
500
362
|
textStyle: AD.TextStyle.TextStyle,
|
|
501
363
|
atom: AD.Atom.Atom,
|
|
502
|
-
alignment:
|
|
364
|
+
alignment: PdfKitAlignment,
|
|
503
365
|
availableWidth: number,
|
|
504
366
|
isFirstAtom: boolean,
|
|
505
367
|
isLastAtom: boolean
|
|
@@ -515,11 +377,10 @@ function renderAtom(
|
|
|
515
377
|
alignment,
|
|
516
378
|
isFirstAtom,
|
|
517
379
|
isLastAtom,
|
|
518
|
-
availableWidth
|
|
519
380
|
);
|
|
520
381
|
return;
|
|
521
382
|
case "TextRun":
|
|
522
|
-
renderTextRun(resources, pdfKit, finalRect, textStyle, atom, alignment, isFirstAtom, isLastAtom
|
|
383
|
+
renderTextRun(resources, pdfKit, finalRect, textStyle, atom, alignment, isFirstAtom, isLastAtom);
|
|
523
384
|
return;
|
|
524
385
|
case "Image":
|
|
525
386
|
renderImage(resources, pdfKit, finalRect, textStyle, atom);
|
|
@@ -553,10 +414,9 @@ function renderTextField(
|
|
|
553
414
|
finalRect: AD.Rect.Rect,
|
|
554
415
|
textStyle: AD.TextStyle.TextStyle,
|
|
555
416
|
textField: AD.TextField.TextField,
|
|
556
|
-
alignment:
|
|
417
|
+
alignment: PdfKitAlignment,
|
|
557
418
|
isFirstAtom: boolean,
|
|
558
419
|
isLastAtom: boolean,
|
|
559
|
-
availableWidth: number
|
|
560
420
|
): void {
|
|
561
421
|
const style = AD.Resources.getStyle(
|
|
562
422
|
textStyle,
|
|
@@ -575,14 +435,13 @@ function renderTextField(
|
|
|
575
435
|
alignment,
|
|
576
436
|
isFirstAtom,
|
|
577
437
|
isLastAtom,
|
|
578
|
-
availableWidth
|
|
579
438
|
);
|
|
580
439
|
return;
|
|
581
440
|
case "PageNumber":
|
|
582
441
|
case "TotalPages":
|
|
583
442
|
case "PageNumberOf":
|
|
584
443
|
if (textField.text) {
|
|
585
|
-
drawText(pdfKit, finalRect, style, textField.text, alignment, isFirstAtom, isLastAtom
|
|
444
|
+
drawText(pdfKit, finalRect, style, textField.text, alignment, isFirstAtom, isLastAtom);
|
|
586
445
|
}
|
|
587
446
|
return;
|
|
588
447
|
}
|
|
@@ -594,10 +453,9 @@ function renderTextRun(
|
|
|
594
453
|
finalRect: AD.Rect.Rect,
|
|
595
454
|
textStyle: AD.TextStyle.TextStyle,
|
|
596
455
|
textRun: AD.TextRun.TextRun,
|
|
597
|
-
alignment:
|
|
456
|
+
alignment: PdfKitAlignment,
|
|
598
457
|
isFirstAtom: boolean,
|
|
599
458
|
isLastAtom: boolean,
|
|
600
|
-
availableWidth: number
|
|
601
459
|
): void {
|
|
602
460
|
const style = AD.Resources.getNestedStyle(
|
|
603
461
|
textStyle,
|
|
@@ -607,8 +465,7 @@ function renderTextRun(
|
|
|
607
465
|
resources,
|
|
608
466
|
textRun.nestedStyleNames || []
|
|
609
467
|
) as AD.TextStyle.TextStyle;
|
|
610
|
-
|
|
611
|
-
drawText(pdf, finalRect, style, textRun.text, textAlignment, isFirstAtom, isLastAtom, availableWidth);
|
|
468
|
+
drawText(pdf, finalRect, style, textRun.text, alignment, isFirstAtom, isLastAtom);
|
|
612
469
|
}
|
|
613
470
|
|
|
614
471
|
function renderHyperLink(
|
|
@@ -617,7 +474,7 @@ function renderHyperLink(
|
|
|
617
474
|
finalRect: AD.Rect.Rect,
|
|
618
475
|
textStyle: AD.TextStyle.TextStyle,
|
|
619
476
|
hyperLink: AD.HyperLink.HyperLink,
|
|
620
|
-
alignment:
|
|
477
|
+
alignment: PdfKitAlignment,
|
|
621
478
|
isFirstAtom: boolean,
|
|
622
479
|
isLastAtom: boolean,
|
|
623
480
|
availableWidth: number
|
|
@@ -629,8 +486,7 @@ function renderHyperLink(
|
|
|
629
486
|
hyperLink.styleName,
|
|
630
487
|
resources
|
|
631
488
|
) as AD.TextStyle.TextStyle;
|
|
632
|
-
|
|
633
|
-
drawHyperLink(pdf, finalRect, style, hyperLink, textAlignment, isFirstAtom, isLastAtom, availableWidth);
|
|
489
|
+
drawHyperLink(pdf, finalRect, style, hyperLink, alignment, isFirstAtom, isLastAtom, availableWidth);
|
|
634
490
|
}
|
|
635
491
|
|
|
636
492
|
function renderTocSeparator(
|
|
@@ -647,7 +503,7 @@ function drawHyperLink(
|
|
|
647
503
|
finalRect: AD.Rect.Rect,
|
|
648
504
|
textStyle: AD.TextStyle.TextStyle,
|
|
649
505
|
hyperLink: AD.HyperLink.HyperLink,
|
|
650
|
-
alignment:
|
|
506
|
+
alignment: PdfKitAlignment,
|
|
651
507
|
isFirstAtom: boolean,
|
|
652
508
|
isLastAtom: boolean,
|
|
653
509
|
availableWidth: number
|
|
@@ -711,12 +567,12 @@ function drawHyperLink(
|
|
|
711
567
|
}
|
|
712
568
|
}
|
|
713
569
|
|
|
714
|
-
function drawText(
|
|
570
|
+
/*function drawText(
|
|
715
571
|
pdf: PDFKit.PDFDocument,
|
|
716
572
|
finalRect: AD.Rect.Rect,
|
|
717
573
|
textStyle: AD.TextStyle.TextStyle,
|
|
718
574
|
text: string,
|
|
719
|
-
alignment:
|
|
575
|
+
alignment: PdfKitAlignment,
|
|
720
576
|
isFirstAtom: boolean,
|
|
721
577
|
isLastAtom: boolean,
|
|
722
578
|
availableWidth: number
|
|
@@ -759,6 +615,71 @@ function drawText(
|
|
|
759
615
|
});
|
|
760
616
|
}
|
|
761
617
|
|
|
618
|
+
resetTextOffset(pdf, textStyle);
|
|
619
|
+
}*/
|
|
620
|
+
|
|
621
|
+
function drawText(
|
|
622
|
+
pdf: PDFKit.PDFDocument,
|
|
623
|
+
finalRect: AD.Rect.Rect,
|
|
624
|
+
textStyle: AD.TextStyle.TextStyle,
|
|
625
|
+
text: string,
|
|
626
|
+
alignment: PdfKitAlignment,
|
|
627
|
+
isFirst: boolean,
|
|
628
|
+
isEnd: boolean,
|
|
629
|
+
): void {
|
|
630
|
+
const font = getFontNameStyle(textStyle);
|
|
631
|
+
const fontSize = AD.TextStyle.calculateFontSize(textStyle, 10);
|
|
632
|
+
pdf
|
|
633
|
+
.font(font)
|
|
634
|
+
.fontSize(fontSize)
|
|
635
|
+
.fillColor(textStyle.color || "black", textStyle.opacity ?? 1.0);
|
|
636
|
+
|
|
637
|
+
applyTextOffset(pdf, textStyle);
|
|
638
|
+
|
|
639
|
+
switch(alignment) {
|
|
640
|
+
case "justify": {
|
|
641
|
+
pdf.text(text, finalRect.x, finalRect.y, {
|
|
642
|
+
width: Infinity,
|
|
643
|
+
underline: textStyle.underline || false,
|
|
644
|
+
continued: false,
|
|
645
|
+
indent: textStyle.indent || 0,
|
|
646
|
+
baseline: textStyle.baseline || "top",
|
|
647
|
+
strike: textStyle.strike,
|
|
648
|
+
...(textStyle.characterSpacing !== undefined ? { characterSpacing: textStyle.characterSpacing } : {}),
|
|
649
|
+
...(textStyle.lineGap !== undefined ? { lineGap: textStyle.lineGap } : {}),
|
|
650
|
+
});
|
|
651
|
+
break;
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
|
|
655
|
+
|
|
656
|
+
default: {
|
|
657
|
+
if(isFirst) {
|
|
658
|
+
pdf.text(text, finalRect.x, finalRect.y, {
|
|
659
|
+
width: Infinity,
|
|
660
|
+
underline: textStyle.underline || false,
|
|
661
|
+
continued: !isEnd,
|
|
662
|
+
indent: textStyle.indent || 0,
|
|
663
|
+
baseline: textStyle.baseline || "top",
|
|
664
|
+
strike: textStyle.strike,
|
|
665
|
+
...(textStyle.characterSpacing !== undefined ? { characterSpacing: textStyle.characterSpacing } : {}),
|
|
666
|
+
...(textStyle.lineGap !== undefined ? { lineGap: textStyle.lineGap } : {}),
|
|
667
|
+
});
|
|
668
|
+
} else {
|
|
669
|
+
pdf.text(text, {
|
|
670
|
+
width: Infinity,
|
|
671
|
+
underline: textStyle.underline || false,
|
|
672
|
+
continued: !isEnd,
|
|
673
|
+
indent: textStyle.indent || 0,
|
|
674
|
+
baseline: textStyle.baseline || "top",
|
|
675
|
+
strike: textStyle.strike,
|
|
676
|
+
...(textStyle.characterSpacing !== undefined ? { characterSpacing: textStyle.characterSpacing } : {}),
|
|
677
|
+
...(textStyle.lineGap !== undefined ? { lineGap: textStyle.lineGap } : {}),
|
|
678
|
+
});
|
|
679
|
+
}
|
|
680
|
+
break;
|
|
681
|
+
}
|
|
682
|
+
}
|
|
762
683
|
resetTextOffset(pdf, textStyle);
|
|
763
684
|
}
|
|
764
685
|
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import * as AD from "../../abstract-document/index.js";
|
|
2
|
+
import { getFontNameStyle } from "./font.js";
|
|
3
|
+
|
|
4
|
+
export type PdfKitAlignment = PDFKit.Mixins.TextOptions["align"];
|
|
5
|
+
|
|
6
|
+
export function rowsSplit(rows: ReadonlyArray<ReadonlyArray<AD.Atom.Atom>>, availableWidth: number, desiredSizes: Map<{}, AD.Size.Size>, alignment: PdfKitAlignment): ReadonlyArray<ReadonlyArray<AD.Atom.Atom>> {
|
|
7
|
+
const newRows: Array<ReadonlyArray<AD.Atom.Atom>> = [];
|
|
8
|
+
|
|
9
|
+
for(const row of rows) {
|
|
10
|
+
if(row.length <= 1) {
|
|
11
|
+
newRows.push(row);
|
|
12
|
+
continue;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const width = row.reduce((a, b) => a + getDesiredSize(b, desiredSizes).width, 0);
|
|
16
|
+
if(width <= availableWidth) {
|
|
17
|
+
newRows.push(row);
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
//we need to split it, because it doesn't fit
|
|
22
|
+
let currentRow: Array<AD.Atom.Atom> = [];
|
|
23
|
+
let currentWidth = 0;
|
|
24
|
+
let lastWasSpace = false;
|
|
25
|
+
|
|
26
|
+
for(let i = 0; i < row.length; i++) {
|
|
27
|
+
const atom = row[i];
|
|
28
|
+
|
|
29
|
+
const width = getDesiredSize(atom, desiredSizes).width;
|
|
30
|
+
|
|
31
|
+
if(atom.type !== "TextRun") {
|
|
32
|
+
currentRow.push(atom);
|
|
33
|
+
currentWidth += width;
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const isSpace = atom.text.replaceAll(/[\p{Zs}]/ug, "").length === 0;
|
|
38
|
+
const lastSpace = lastWasSpace;
|
|
39
|
+
lastWasSpace = isSpace;
|
|
40
|
+
|
|
41
|
+
//if the next atom is a space, we need to split this row early if it doesnt fit
|
|
42
|
+
const nextAtom = row[i + 1];
|
|
43
|
+
const nextWidthIfSpace =
|
|
44
|
+
!isSpace
|
|
45
|
+
&& nextAtom
|
|
46
|
+
&& nextAtom.type === "TextRun"
|
|
47
|
+
&& nextAtom.text.replaceAll(/[\p{Zs}]/ug, "").length === 0
|
|
48
|
+
? getDesiredSize(nextAtom, desiredSizes).width
|
|
49
|
+
: 0;
|
|
50
|
+
|
|
51
|
+
if(isSpace && currentWidth === 0 && i !== 0 && (alignment === "left" || alignment === "justify")) {
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if((currentWidth + width + nextWidthIfSpace) < availableWidth) {
|
|
56
|
+
currentRow.push(atom);
|
|
57
|
+
currentWidth += width;
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
//was it a space??
|
|
62
|
+
if(isSpace) {
|
|
63
|
+
newRows.push(currentRow);
|
|
64
|
+
currentRow = [];
|
|
65
|
+
currentWidth = 0;
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
newRows.push((lastSpace && (alignment === "right" || alignment === "justify")) ? currentRow.slice(0, -1) : currentRow);
|
|
70
|
+
currentRow = [atom];
|
|
71
|
+
currentWidth = width;
|
|
72
|
+
}
|
|
73
|
+
newRows.push((lastWasSpace && (alignment === "right" || alignment === "justify")) ? currentRow.slice(0, -1) : currentRow);
|
|
74
|
+
}
|
|
75
|
+
return newRows;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function rowsCombineTextRuns(resources: AD.Resources.Resources, pdf: PDFKit.PDFDocument, rows: ReadonlyArray<ReadonlyArray<AD.Atom.Atom>>, desiredSizes: Map<{}, AD.Size.Size>, alignment: PdfKitAlignment, defaultStyle: AD.TextStyle.TextStyle): { newDesiredSizes: Map<{}, AD.Size.Size>; combinedRows: ReadonlyArray<ReadonlyArray<AD.Atom.Atom>> } {
|
|
79
|
+
if(alignment === "justify") {
|
|
80
|
+
return { combinedRows: rows, newDesiredSizes: desiredSizes };
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
let currentString = "";
|
|
84
|
+
let currentHeight = 0;
|
|
85
|
+
let current: AD.Atom.Atom | undefined = undefined;
|
|
86
|
+
let currentStyle: string = "";
|
|
87
|
+
|
|
88
|
+
const newRows: Array<ReadonlyArray<AD.Atom.Atom>> = [];
|
|
89
|
+
for(const row of rows) {
|
|
90
|
+
const newRow: Array<AD.Atom.Atom> = [];
|
|
91
|
+
let isFirst = true;
|
|
92
|
+
|
|
93
|
+
for(let i = 0; i < row.length; i++) {
|
|
94
|
+
const atom = row[i];
|
|
95
|
+
const isLast = i === row.length - 1;
|
|
96
|
+
const measurement = getDesiredSize(atom, desiredSizes);
|
|
97
|
+
|
|
98
|
+
if(atom.type !== "TextRun") {
|
|
99
|
+
if(current !== undefined) {
|
|
100
|
+
const newTextRun = {
|
|
101
|
+
...current,
|
|
102
|
+
text: currentString
|
|
103
|
+
};
|
|
104
|
+
if(isFirst && alignment === "left") {
|
|
105
|
+
while(currentString.startsWith(" ")) {
|
|
106
|
+
currentString = currentString.slice(1);
|
|
107
|
+
}
|
|
108
|
+
isFirst = false;
|
|
109
|
+
} else if(isFirst) {
|
|
110
|
+
isFirst = false;
|
|
111
|
+
}
|
|
112
|
+
newRow.push(newTextRun);
|
|
113
|
+
desiredSizes.set(newTextRun, { width: stringWidth(pdf, currentString, current.style ?? defaultStyle), height: currentHeight });
|
|
114
|
+
currentString = "";
|
|
115
|
+
currentStyle = "";
|
|
116
|
+
currentHeight = 0;
|
|
117
|
+
current = undefined;
|
|
118
|
+
}
|
|
119
|
+
newRow.push(atom);
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const style = JSON.stringify(AD.Resources.getNestedStyle(
|
|
124
|
+
defaultStyle,
|
|
125
|
+
atom.style,
|
|
126
|
+
"TextStyle",
|
|
127
|
+
atom.styleName,
|
|
128
|
+
resources,
|
|
129
|
+
atom.nestedStyleNames || []
|
|
130
|
+
));
|
|
131
|
+
|
|
132
|
+
if(current === undefined) {
|
|
133
|
+
currentString = atom.text;
|
|
134
|
+
current = atom;
|
|
135
|
+
currentHeight = Math.max(measurement.height, currentHeight);
|
|
136
|
+
currentStyle = style;
|
|
137
|
+
} else if(style !== currentStyle) {
|
|
138
|
+
const newTextRun = {
|
|
139
|
+
...current,
|
|
140
|
+
text: currentString
|
|
141
|
+
};
|
|
142
|
+
if(isFirst && alignment === "left") {
|
|
143
|
+
while(currentString.startsWith(" ")) {
|
|
144
|
+
currentString = currentString.slice(1);
|
|
145
|
+
}
|
|
146
|
+
isFirst = false;
|
|
147
|
+
} else if(isFirst) {
|
|
148
|
+
isFirst = false;
|
|
149
|
+
}
|
|
150
|
+
newRow.push(newTextRun);
|
|
151
|
+
desiredSizes.set(newTextRun, { width: stringWidth(pdf, currentString, current.style ?? defaultStyle), height: currentHeight });
|
|
152
|
+
currentString = atom.text;
|
|
153
|
+
currentHeight = Math.max(measurement.height, currentHeight);
|
|
154
|
+
current = atom;
|
|
155
|
+
currentStyle = style;
|
|
156
|
+
} else {
|
|
157
|
+
currentString += atom.text;
|
|
158
|
+
currentHeight = Math.max(measurement.height, currentHeight);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if(isLast) {
|
|
162
|
+
if(current) {
|
|
163
|
+
//does the last contain spaces at the end?
|
|
164
|
+
if(alignment === "right") {
|
|
165
|
+
while(currentString.endsWith(" ")) {
|
|
166
|
+
currentString = currentString.slice(0, -1);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
if(isFirst && alignment === "left") {
|
|
170
|
+
while(currentString.startsWith(" ")) {
|
|
171
|
+
currentString = currentString.slice(1);
|
|
172
|
+
}
|
|
173
|
+
isFirst = false;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const newTextRun: AD.Atom.Atom = {
|
|
177
|
+
...current,
|
|
178
|
+
text: currentString,
|
|
179
|
+
}
|
|
180
|
+
newRow.push(newTextRun);
|
|
181
|
+
desiredSizes.set(newTextRun, { width: stringWidth(pdf, currentString, current.style ?? defaultStyle), height: currentHeight });
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
current = undefined;
|
|
186
|
+
currentHeight = 0;
|
|
187
|
+
currentString = "";
|
|
188
|
+
currentStyle = "";
|
|
189
|
+
newRows.push(newRow);
|
|
190
|
+
}
|
|
191
|
+
return { newDesiredSizes: desiredSizes, combinedRows: newRows };
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function stringWidth(
|
|
195
|
+
pdf: PDFKit.PDFDocument,
|
|
196
|
+
text: string,
|
|
197
|
+
textStyle: AD.TextStyle.TextStyle,
|
|
198
|
+
): number {
|
|
199
|
+
const font = getFontNameStyle(textStyle);
|
|
200
|
+
const fontSize = AD.TextStyle.calculateFontSize(textStyle, 10);
|
|
201
|
+
pdf
|
|
202
|
+
.font(font)
|
|
203
|
+
.fontSize(fontSize)
|
|
204
|
+
.fillColor(textStyle.color || "black");
|
|
205
|
+
|
|
206
|
+
const textOptions = {
|
|
207
|
+
underline: textStyle.underline || false,
|
|
208
|
+
indent: textStyle.indent || 0,
|
|
209
|
+
lineBreak: false,
|
|
210
|
+
...(textStyle.characterSpacing !== undefined ? { characterSpacing: textStyle.characterSpacing } : {}),
|
|
211
|
+
...(textStyle.lineGap !== undefined ? { lineGap: textStyle.lineGap } : {}),
|
|
212
|
+
};
|
|
213
|
+
return pdf.widthOfString(text, textOptions);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function getDesiredSize(element: {}, desiredSizes: Map<{}, AD.Size.Size>): AD.Size.Size {
|
|
217
|
+
const size = desiredSizes.get(element);
|
|
218
|
+
if (size) {
|
|
219
|
+
return size;
|
|
220
|
+
}
|
|
221
|
+
throw new Error("Could not find size for element!");
|
|
222
|
+
}
|
|
@@ -55,10 +55,10 @@ export const StyleName = `<xs:complexType name="StyleName">
|
|
|
55
55
|
<xs:attribute name="alignment">
|
|
56
56
|
<xs:simpleType>
|
|
57
57
|
<xs:restriction base="xs:string">
|
|
58
|
-
<xs:enumeration value="
|
|
59
|
-
<xs:enumeration value="
|
|
60
|
-
<xs:enumeration value="
|
|
61
|
-
<xs:enumeration value="
|
|
58
|
+
<xs:enumeration value="Start" />
|
|
59
|
+
<xs:enumeration value="Center" />
|
|
60
|
+
<xs:enumeration value="End" />
|
|
61
|
+
<xs:enumeration value="Justify" />
|
|
62
62
|
</xs:restriction>
|
|
63
63
|
</xs:simpleType>
|
|
64
64
|
</xs:attribute>
|
|
@@ -217,16 +217,6 @@ export const textStyle = `<xs:complexType name="TextStyle">
|
|
|
217
217
|
<xs:attribute name="indent" type="xs:decimal" />
|
|
218
218
|
<xs:attribute name="color" type="xs:string" />
|
|
219
219
|
<xs:attribute name="fontFamily" type="xs:string" />
|
|
220
|
-
<xs:attribute name="alignment">
|
|
221
|
-
<xs:simpleType>
|
|
222
|
-
<xs:restriction base="xs:string">
|
|
223
|
-
<xs:enumeration value="left" />
|
|
224
|
-
<xs:enumeration value="center" />
|
|
225
|
-
<xs:enumeration value="right" />
|
|
226
|
-
<xs:enumeration value="justify" />
|
|
227
|
-
</xs:restriction>
|
|
228
|
-
</xs:simpleType>
|
|
229
|
-
</xs:attribute>
|
|
230
220
|
<xs:attribute name="baseline">
|
|
231
221
|
<xs:simpleType>
|
|
232
222
|
<xs:restriction base="xs:string">
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"to-base-64.d.ts","sourceRoot":"","sources":["../../../src/abstract-document-exporters/shared/to-base-64.ts"],"names":[],"mappings":"AAAA,wBAAgB,cAAc,CAAC,EAAE,EAAE,UAAU,GAAG,MAAM,CAarD;AAED,eAAO,MAAM,YAAY,wBAAwB,CAAC"}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.rawSvgPrefix = void 0;
|
|
4
|
-
exports.toBase64String = toBase64String;
|
|
5
|
-
function toBase64String(u8) {
|
|
6
|
-
const imageFormat = u8[0] === 0xff && u8[1] === 0xd8 ? "image/jpeg" : "image/png";
|
|
7
|
-
// Node
|
|
8
|
-
if (typeof Buffer !== "undefined") {
|
|
9
|
-
return `data:${imageFormat};base64,${Buffer.from(u8).toString("base64")}`;
|
|
10
|
-
}
|
|
11
|
-
// Browser
|
|
12
|
-
let bin = "";
|
|
13
|
-
for (const e of u8) {
|
|
14
|
-
bin += String.fromCharCode(e);
|
|
15
|
-
}
|
|
16
|
-
return `data:${imageFormat};base64,${btoa(bin)}`;
|
|
17
|
-
}
|
|
18
|
-
exports.rawSvgPrefix = "data:image/svg+xml,";
|
|
19
|
-
//# sourceMappingURL=to-base-64.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"to-base-64.js","sourceRoot":"","sources":["../../../src/abstract-document-exporters/shared/to-base-64.ts"],"names":[],"mappings":";;;AAAA,wCAaC;AAbD,SAAgB,cAAc,CAAC,EAAc;IAC3C,MAAM,WAAW,GAAG,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,WAAW,CAAC;IAClF,OAAO;IACP,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;QAClC,OAAO,QAAQ,WAAW,WAAW,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;IAC5E,CAAC;IACD,UAAU;IACV,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,KAAK,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;QACnB,GAAG,IAAI,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAChC,CAAC;IAED,OAAO,QAAQ,WAAW,WAAW,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;AACnD,CAAC;AAEY,QAAA,YAAY,GAAG,qBAAqB,CAAC"}
|