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.
Files changed (42) hide show
  1. package/CHANGELOG.md +2 -1
  2. package/lib/abstract-document/markdown/markdown.d.ts.map +1 -1
  3. package/lib/abstract-document/markdown/markdown.js +1 -10
  4. package/lib/abstract-document/markdown/markdown.js.map +1 -1
  5. package/lib/abstract-document/section-elements/paragraph.d.ts +0 -2
  6. package/lib/abstract-document/section-elements/paragraph.d.ts.map +1 -1
  7. package/lib/abstract-document/section-elements/paragraph.js +1 -2
  8. package/lib/abstract-document/section-elements/paragraph.js.map +1 -1
  9. package/lib/abstract-document/styles/text-style.d.ts +0 -3
  10. package/lib/abstract-document/styles/text-style.d.ts.map +1 -1
  11. package/lib/abstract-document/styles/text-style.js +0 -1
  12. package/lib/abstract-document/styles/text-style.js.map +1 -1
  13. package/lib/abstract-document-exporters/pdf/measure.js +13 -3
  14. package/lib/abstract-document-exporters/pdf/measure.js.map +1 -1
  15. package/lib/abstract-document-exporters/pdf/pre-process.js +23 -1
  16. package/lib/abstract-document-exporters/pdf/pre-process.js.map +1 -1
  17. package/lib/abstract-document-exporters/pdf/render.d.ts.map +1 -1
  18. package/lib/abstract-document-exporters/pdf/render.js +116 -152
  19. package/lib/abstract-document-exporters/pdf/render.js.map +1 -1
  20. package/lib/abstract-document-exporters/pdf/textRunRow.d.ts +8 -0
  21. package/lib/abstract-document-exporters/pdf/textRunRow.d.ts.map +1 -0
  22. package/lib/abstract-document-exporters/pdf/textRunRow.js +225 -0
  23. package/lib/abstract-document-exporters/pdf/textRunRow.js.map +1 -0
  24. package/lib/abstract-document-xml/xsd-template/styles.d.ts +2 -2
  25. package/lib/abstract-document-xml/xsd-template/styles.d.ts.map +1 -1
  26. package/lib/abstract-document-xml/xsd-template/styles.js +4 -14
  27. package/lib/abstract-document-xml/xsd-template/styles.js.map +1 -1
  28. package/lib/abstract-document-xml/xsd-template/xsd-template.d.ts +2 -2
  29. package/lib/abstract-document-xml/xsd-template/xsd-template.d.ts.map +1 -1
  30. package/package.json +2 -2
  31. package/src/abstract-document/markdown/markdown.ts +1 -11
  32. package/src/abstract-document/section-elements/paragraph.ts +1 -4
  33. package/src/abstract-document/styles/text-style.ts +0 -4
  34. package/src/abstract-document-exporters/pdf/measure.ts +15 -3
  35. package/src/abstract-document-exporters/pdf/pre-process.ts +22 -1
  36. package/src/abstract-document-exporters/pdf/render.ts +93 -172
  37. package/src/abstract-document-exporters/pdf/textRunRow.ts +222 -0
  38. package/src/abstract-document-xml/xsd-template/styles.ts +4 -14
  39. package/lib/abstract-document-exporters/shared/to-base-64.d.ts +0 -3
  40. package/lib/abstract-document-exporters/shared/to-base-64.d.ts.map +0 -1
  41. package/lib/abstract-document-exporters/shared/to-base-64.js +0 -19
  42. 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
- for (let row of rows) {
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, desiredSizes).width, 0);
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: Texts with multiple atoms with width over the available width are not supported.
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, desiredSizes);
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 === "justify" ? justificationWidth : 0);
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
- const width = getDesiredSize(atom, desiredSizes).width;
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): AD.TextStyle.TextAlignment {
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: AD.TextStyle.TextAlignment,
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, availableWidth);
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: AD.TextStyle.TextAlignment,
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, availableWidth);
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: AD.TextStyle.TextAlignment,
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
- const textAlignment = style.alignment ? style.alignment : alignment;
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: AD.TextStyle.TextAlignment,
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
- const textAlignment = style.alignment ? style.alignment : alignment;
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: AD.TextStyle.TextAlignment,
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: AD.TextStyle.TextAlignment,
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="left" />
59
- <xs:enumeration value="center" />
60
- <xs:enumeration value="right" />
61
- <xs:enumeration value="justify" />
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,3 +0,0 @@
1
- export declare function toBase64String(u8: Uint8Array): string;
2
- export declare const rawSvgPrefix = "data:image/svg+xml,";
3
- //# sourceMappingURL=to-base-64.d.ts.map
@@ -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"}