@pdfme/schemas 6.1.0 → 6.1.1-dev.5

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.
@@ -1,17 +1,23 @@
1
- import { A as FONT_SIZE_ADJUSTMENT, B as VERTICAL_ALIGN_MIDDLE, C as DEFAULT_ALIGNMENT, D as DEFAULT_TEXT_FORMAT, E as DEFAULT_FONT_VARIANT_FALLBACK, F as SYNTHETIC_BOLD_CSS_TEXT_SHADOW, I as SYNTHETIC_BOLD_OFFSET_RATIO, L as TEXT_FORMAT_INLINE_MARKDOWN, M as FONT_VARIANT_FALLBACK_PLAIN, N as FONT_VARIANT_FALLBACK_SYNTHETIC, O as DYNAMIC_FIT_HORIZONTAL, P as PLACEHOLDER_FONT_COLOR, R as TEXT_FORMAT_PLAIN, S as CODE_HORIZONTAL_PADDING, T as DEFAULT_FONT_COLOR, _ as widthOfTextAtSize, b as ALIGN_RIGHT, d as getBrowserVerticalFontAdjustments, f as getFontDescentInPt, g as splitTextToSize, h as isFirefox, j as FONT_VARIANT_FALLBACK_ERROR, k as DYNAMIC_FIT_VERTICAL, l as calculateDynamicFontSize, m as heightOfFontAtSize, p as getFontKitFont, s as HEX_COLOR_PATTERN, u as fetchRemoteFontData, v as ALIGN_CENTER, w as DEFAULT_DYNAMIC_FIT, x as CODE_BACKGROUND_COLOR, y as ALIGN_JUSTIFY, z as VERTICAL_ALIGN_BOTTOM } from "./dynamicTemplate-Dsrw11aL.js";
1
+ import { A as TEXT_FORMAT_INLINE_MARKDOWN, C as FONT_SIZE_ADJUSTMENT, D as PLACEHOLDER_FONT_COLOR, E as FONT_VARIANT_FALLBACK_SYNTHETIC, M as VERTICAL_ALIGN_BOTTOM, N as VERTICAL_ALIGN_MIDDLE, O as SYNTHETIC_BOLD_CSS_TEXT_SHADOW, S as DYNAMIC_FIT_VERTICAL, T as FONT_VARIANT_FALLBACK_PLAIN, _ as DEFAULT_DYNAMIC_FIT, a as getFontKitFont, b as DEFAULT_TEXT_FORMAT, c as splitTextToSize, d as ALIGN_JUSTIFY, g as DEFAULT_ALIGNMENT, h as CODE_HORIZONTAL_PADDING, i as getFontDescentInPt, j as TEXT_FORMAT_PLAIN, k as SYNTHETIC_BOLD_OFFSET_RATIO, l as widthOfTextAtSize, m as CODE_BACKGROUND_COLOR, n as fetchRemoteFontData, o as heightOfFontAtSize, p as ALIGN_RIGHT, r as getBrowserVerticalFontAdjustments, s as isFirefox, t as calculateDynamicFontSize, u as ALIGN_CENTER, v as DEFAULT_FONT_COLOR, w as FONT_VARIANT_FALLBACK_ERROR, x as DYNAMIC_FIT_HORIZONTAL, y as DEFAULT_FONT_VARIANT_FALLBACK } from "./helper-6FilIoVM.js";
2
+ import { c as HEX_COLOR_PATTERN } from "./dynamicTemplate-DslOH4FZ.js";
2
3
  import { convertForPdfLayoutProps, createSvgStr, hex2PrintingColor, isEditable, rotatePoint } from "./utils.js";
3
- import { DEFAULT_FONT_NAME, getDefaultFont, getFallbackFontName, mm2pt, pt2mm } from "@pdfme/common";
4
+ import { DEFAULT_FONT_NAME, getDefaultFont, getFallbackFontName, getInternalLinkTarget, mm2pt, normalizeLinkHref, normalizeSafeLinkUri, pt2mm, registerInternalLinkAnnotation } from "@pdfme/common";
5
+ import { PDFName, PDFString } from "@pdfme/pdf-lib";
4
6
  import { AlignCenter, AlignJustify, AlignLeft, AlignRight, ArrowDownToLine, ArrowUpToLine, Strikethrough, TextCursorInput, Underline } from "lucide";
5
7
  //#region src/text/inlineMarkdown.ts
6
8
  var MARKDOWN_ESCAPABLE_CHARS = new Set([
7
9
  "\\",
8
10
  "*",
9
11
  "~",
10
- "`"
12
+ "`",
13
+ "[",
14
+ "]",
15
+ "(",
16
+ ")"
11
17
  ]);
12
- var MARKDOWN_ESCAPE_PATTERN = /[\\*~`]/g;
13
- var MARKDOWN_UNESCAPE_PATTERN = /\\([\\*~`])/g;
14
- var sameStyle = (a, b) => Boolean(a.bold) === Boolean(b.bold) && Boolean(a.italic) === Boolean(b.italic) && Boolean(a.strikethrough) === Boolean(b.strikethrough) && Boolean(a.code) === Boolean(b.code);
18
+ var MARKDOWN_ESCAPE_PATTERN = /[\\*~`[\]()]/g;
19
+ var MARKDOWN_UNESCAPE_PATTERN = /\\([\\*~`[\]()])/g;
20
+ var sameStyle = (a, b) => Boolean(a.bold) === Boolean(b.bold) && Boolean(a.italic) === Boolean(b.italic) && Boolean(a.strikethrough) === Boolean(b.strikethrough) && Boolean(a.code) === Boolean(b.code) && a.href === b.href;
15
21
  var appendRun = (runs, text, style) => {
16
22
  if (!text) return;
17
23
  const lastRun = runs.at(-1);
@@ -24,7 +30,8 @@ var appendRun = (runs, text, style) => {
24
30
  ...style.bold ? { bold: true } : {},
25
31
  ...style.italic ? { italic: true } : {},
26
32
  ...style.strikethrough ? { strikethrough: true } : {},
27
- ...style.code ? { code: true } : {}
33
+ ...style.code ? { code: true } : {},
34
+ ...style.href ? { href: style.href } : {}
28
35
  });
29
36
  };
30
37
  var findClosingDelimiter = (value, delimiter, from) => {
@@ -51,6 +58,50 @@ var getDelimiter = (value, index) => {
51
58
  if (value[index] === "*") return "*";
52
59
  return "";
53
60
  };
61
+ var findLinkLabelEnd = (value, from, to) => {
62
+ for (let index = from; index < to; index += 1) {
63
+ if (value[index] === "\\") {
64
+ index += 1;
65
+ continue;
66
+ }
67
+ if (value[index] === "]") return index;
68
+ }
69
+ return -1;
70
+ };
71
+ var findLinkDestinationEnd = (value, from, to) => {
72
+ let depth = 0;
73
+ for (let index = from; index < to; index += 1) {
74
+ if (value[index] === "\\") {
75
+ index += 1;
76
+ continue;
77
+ }
78
+ if (value[index] === "(") {
79
+ depth += 1;
80
+ continue;
81
+ }
82
+ if (value[index] === ")") {
83
+ if (depth === 0) return index;
84
+ depth -= 1;
85
+ }
86
+ }
87
+ return -1;
88
+ };
89
+ var parseLinkAt = (value, index, to) => {
90
+ if (value[index] !== "[") return void 0;
91
+ const labelEnd = findLinkLabelEnd(value, index + 1, to);
92
+ if (labelEnd === -1 || value[labelEnd + 1] !== "(") return void 0;
93
+ const destinationStart = labelEnd + 2;
94
+ const destinationEnd = findLinkDestinationEnd(value, destinationStart, to);
95
+ if (destinationEnd === -1) return void 0;
96
+ const safeHref = normalizeLinkHref(value.slice(destinationStart, destinationEnd).replace(MARKDOWN_UNESCAPE_PATTERN, "$1"));
97
+ if (!safeHref) return void 0;
98
+ return {
99
+ labelStart: index + 1,
100
+ labelEnd,
101
+ href: safeHref,
102
+ end: destinationEnd + 1
103
+ };
104
+ };
54
105
  var mergeStyle = (style, delimiter) => {
55
106
  if (delimiter === "***") return {
56
107
  ...style,
@@ -85,6 +136,16 @@ var parseRange = (value, from, to, style) => {
85
136
  index += 1;
86
137
  continue;
87
138
  }
139
+ const link = style.href ? void 0 : parseLinkAt(value, index, to);
140
+ if (link) {
141
+ flush();
142
+ parseRange(value, link.labelStart, link.labelEnd, {
143
+ ...style,
144
+ href: link.href
145
+ }).forEach((run) => appendRun(runs, run.text, run));
146
+ index = link.end - 1;
147
+ continue;
148
+ }
88
149
  const delimiter = getDelimiter(value, index);
89
150
  if (!delimiter) {
90
151
  buffer += char;
@@ -422,15 +483,48 @@ var calculateDynamicRichTextFontSize = async (arg) => {
422
483
  return dynamicFontSize;
423
484
  };
424
485
  //#endregion
486
+ //#region src/text/linkAnnotation.ts
487
+ var addUriLinkAnnotation = (arg) => {
488
+ const { pdfDoc, page, uri, rect, borderWidth = 0 } = arg;
489
+ const safeUri = normalizeSafeLinkUri(uri);
490
+ if (!safeUri || rect.width <= 0 || rect.height <= 0) return;
491
+ const annotationRef = pdfDoc.context.register(pdfDoc.context.obj({
492
+ Type: PDFName.of("Annot"),
493
+ Subtype: PDFName.of("Link"),
494
+ Rect: [
495
+ rect.x,
496
+ rect.y,
497
+ rect.x + rect.width,
498
+ rect.y + rect.height
499
+ ],
500
+ Border: [
501
+ 0,
502
+ 0,
503
+ borderWidth
504
+ ],
505
+ A: {
506
+ Type: PDFName.of("Action"),
507
+ S: PDFName.of("URI"),
508
+ URI: PDFString.of(safeUri)
509
+ }
510
+ }));
511
+ page.node.addAnnot(annotationRef);
512
+ };
513
+ //#endregion
425
514
  //#region src/text/richTextPdfRender.ts
426
515
  var getSyntheticBoldWidth = (run, fontSize) => run.syntheticBold ? fontSize * SYNTHETIC_BOLD_OFFSET_RATIO * 2 : 0;
427
516
  var getSyntheticItalicWidth = (run, fontSize) => run.syntheticItalic ? heightOfFontAtSize(run.fontKitFont, fontSize) * Math.tan(12 * Math.PI / 180) : 0;
428
517
  var getRunWidth = (run, fontSize, characterSpacing) => widthOfTextAtSize(run.text, run.fontKitFont, fontSize, characterSpacing) + getSyntheticBoldWidth(run, fontSize) + getSyntheticItalicWidth(run, fontSize);
429
- var getPdfFont = (run, pdfFontObj) => {
518
+ var getPdfFontFromObj = (run, pdfFontObj) => {
430
519
  const pdfFont = pdfFontObj[run.fontName];
431
520
  if (!pdfFont) throw new Error(`[@pdfme/schemas] Missing embedded font "${run.fontName}".`);
432
521
  return pdfFont;
433
522
  };
523
+ var embedFontsForRuns = async (runs, embedPdfFont) => {
524
+ const fontNames = Array.from(new Set(runs.map((run) => run.fontName)));
525
+ const pdfFonts = await Promise.all(fontNames.map(async (fontName) => [fontName, await embedPdfFont(fontName)]));
526
+ return Object.fromEntries(pdfFonts);
527
+ };
434
528
  var drawDecorationLine = (arg) => {
435
529
  const { page, x, y, width, rotate, pivotPoint, fontSize, color, opacity } = arg;
436
530
  if (width <= 0) return;
@@ -448,8 +542,58 @@ var drawDecorationLine = (arg) => {
448
542
  opacity
449
543
  });
450
544
  };
545
+ var getAxisAlignedRect = (arg) => {
546
+ const { x, y, width, height, rotate, pivotPoint } = arg;
547
+ if (rotate.angle === 0) return {
548
+ x,
549
+ y,
550
+ width,
551
+ height
552
+ };
553
+ const points = [
554
+ {
555
+ x,
556
+ y
557
+ },
558
+ {
559
+ x: x + width,
560
+ y
561
+ },
562
+ {
563
+ x: x + width,
564
+ y: y + height
565
+ },
566
+ {
567
+ x,
568
+ y: y + height
569
+ }
570
+ ].map((point) => rotatePoint(point, pivotPoint, rotate.angle));
571
+ const xs = points.map((point) => point.x);
572
+ const ys = points.map((point) => point.y);
573
+ const minX = Math.min(...xs);
574
+ const minY = Math.min(...ys);
575
+ return {
576
+ x: minX,
577
+ y: minY,
578
+ width: Math.max(...xs) - minX,
579
+ height: Math.max(...ys) - minY
580
+ };
581
+ };
582
+ var getLinkAnnotationRect = (arg) => {
583
+ const { run, x, y, width, rotate, pivotPoint, fontSize } = arg;
584
+ const textHeight = heightOfFontAtSize(run.fontKitFont, fontSize);
585
+ const descent = getFontDescentInPt(run.fontKitFont, fontSize);
586
+ return getAxisAlignedRect({
587
+ x,
588
+ y: y + descent,
589
+ width,
590
+ height: textHeight - descent,
591
+ rotate,
592
+ pivotPoint
593
+ });
594
+ };
451
595
  var drawRun = (arg) => {
452
- const { page, pdfLib, run, pdfFont, x, y, rotate, pivotPoint, fontSize, lineHeight, color, opacity, colorType, characterSpacing, strikethrough } = arg;
596
+ const { page, pdfLib, run, pdfFont, x, y, rotate, pivotPoint, fontSize, lineHeight, color, opacity, colorType, characterSpacing, strikethrough, underline } = arg;
453
597
  const runWidth = getRunWidth(run, fontSize, characterSpacing);
454
598
  const textHeight = heightOfFontAtSize(run.fontKitFont, fontSize);
455
599
  if (run.code) {
@@ -484,6 +628,17 @@ var drawRun = (arg) => {
484
628
  color,
485
629
  opacity
486
630
  });
631
+ if (underline && runWidth > 0) drawDecorationLine({
632
+ page,
633
+ x,
634
+ y: y - textHeight / 12,
635
+ width: runWidth,
636
+ rotate,
637
+ pivotPoint,
638
+ fontSize,
639
+ color,
640
+ opacity
641
+ });
487
642
  const drawAt = (drawX) => {
488
643
  const point = rotate.angle === 0 ? {
489
644
  x: drawX,
@@ -511,7 +666,7 @@ var drawRun = (arg) => {
511
666
  }
512
667
  };
513
668
  var renderInlineMarkdownText = async (arg) => {
514
- const { value, schema, font, pdfFontObj, fontKitFont, page, pdfLib, _cache, colorType, fontSize, color, alignment, verticalAlignment, lineHeight, characterSpacing, x, width, height, pageHeight, pivotPoint, rotate, opacity } = arg;
669
+ const { value, schema, font, embedPdfFont, fontKitFont, pdfDoc, page, pdfLib, _cache, colorType, fontSize, color, alignment, verticalAlignment, lineHeight, characterSpacing, x, width, height, pageHeight, pivotPoint, rotate, opacity } = arg;
515
670
  const lines = layoutRichTextLines({
516
671
  runs: await resolveRichTextRuns({
517
672
  runs: parseInlineMarkdown(value),
@@ -523,6 +678,7 @@ var renderInlineMarkdownText = async (arg) => {
523
678
  characterSpacing,
524
679
  boxWidthInPt: width
525
680
  });
681
+ const pdfFontObj = await embedFontsForRuns(lines.flatMap((line) => line.runs), embedPdfFont);
526
682
  const firstLineTextHeight = heightOfFontAtSize(fontKitFont, fontSize);
527
683
  const descent = getFontDescentInPt(fontKitFont, fontSize);
528
684
  const halfLineHeightAdjustment = lineHeight === 0 ? 0 : (lineHeight - 1) * fontSize / 2;
@@ -580,7 +736,7 @@ var renderInlineMarkdownText = async (arg) => {
580
736
  page,
581
737
  pdfLib,
582
738
  run,
583
- pdfFont: getPdfFont(run, pdfFontObj),
739
+ pdfFont: getPdfFontFromObj(run, pdfFontObj),
584
740
  x: currentX,
585
741
  y: yLine,
586
742
  rotate,
@@ -591,25 +747,62 @@ var renderInlineMarkdownText = async (arg) => {
591
747
  opacity,
592
748
  colorType,
593
749
  characterSpacing: spacing,
594
- strikethrough: Boolean(run.strikethrough)
750
+ strikethrough: Boolean(run.strikethrough),
751
+ underline: Boolean(run.href) && !schema.underline
595
752
  });
753
+ if (run.href) {
754
+ const rect = getLinkAnnotationRect({
755
+ run,
756
+ x: currentX,
757
+ y: yLine,
758
+ width: runWidth,
759
+ rotate,
760
+ pivotPoint,
761
+ fontSize
762
+ });
763
+ const targetName = getInternalLinkTarget(run.href);
764
+ if (targetName) registerInternalLinkAnnotation({
765
+ _cache,
766
+ page,
767
+ targetName,
768
+ rect
769
+ });
770
+ else addUriLinkAnnotation({
771
+ pdfDoc,
772
+ page,
773
+ uri: run.href,
774
+ rect
775
+ });
776
+ }
596
777
  return currentX + runWidth + (runIndex === line.runs.length - 1 ? 0 : spacing);
597
778
  }, xLine);
598
779
  });
599
780
  };
600
781
  //#endregion
601
782
  //#region src/text/pdfRender.ts
602
- var embedAndGetFontObj = async (arg) => {
603
- const { pdfDoc, font, _cache } = arg;
604
- if (_cache.has(pdfDoc)) return _cache.get(pdfDoc);
605
- const fontValues = await Promise.all(Object.values(font).map(async (v) => {
606
- let fontData = v.data;
783
+ var PDF_FONT_CACHE_KEY = "text-pdf-font-cache";
784
+ var getPdfFontCache = (_cache) => {
785
+ let pdfFontCache = _cache.get(PDF_FONT_CACHE_KEY);
786
+ if (!pdfFontCache) {
787
+ pdfFontCache = {};
788
+ _cache.set(PDF_FONT_CACHE_KEY, pdfFontCache);
789
+ }
790
+ return pdfFontCache;
791
+ };
792
+ var embedAndGetFont = (arg) => {
793
+ const { pdfDoc, font, fontName, _cache } = arg;
794
+ const pdfFontCache = getPdfFontCache(_cache);
795
+ const cachedFont = pdfFontCache[fontName];
796
+ if (cachedFont) return cachedFont;
797
+ const fontValue = font[fontName];
798
+ if (!fontValue) return Promise.reject(/* @__PURE__ */ new Error(`[@pdfme/schemas] Font "${fontName}" is not found.`));
799
+ const pdfFontPromise = (async () => {
800
+ let fontData = fontValue.data;
607
801
  if (typeof fontData === "string" && fontData.startsWith("http")) fontData = await fetchRemoteFontData(fontData);
608
- return pdfDoc.embedFont(fontData, { subset: typeof v.subset === "undefined" ? true : v.subset });
609
- }));
610
- const fontObj = Object.keys(font).reduce((acc, cur, i) => Object.assign(acc, { [cur]: fontValues[i] }), {});
611
- _cache.set(pdfDoc, fontObj);
612
- return fontObj;
802
+ return pdfDoc.embedFont(fontData, { subset: typeof fontValue.subset === "undefined" ? true : fontValue.subset });
803
+ })();
804
+ pdfFontCache[fontName] = pdfFontPromise;
805
+ return pdfFontPromise;
613
806
  };
614
807
  var getFontProp = ({ value, fontKitFont, schema, colorType, fontSize: resolvedFontSize }) => {
615
808
  const fontSize = resolvedFontSize ?? (schema.dynamicFontSize ? calculateDynamicFontSize({
@@ -627,16 +820,24 @@ var getFontProp = ({ value, fontKitFont, schema, colorType, fontSize: resolvedFo
627
820
  color
628
821
  };
629
822
  };
823
+ var graphemeSegmenter;
824
+ var getGraphemeSegmenter = () => {
825
+ graphemeSegmenter ?? (graphemeSegmenter = new Intl.Segmenter(void 0, { granularity: "grapheme" }));
826
+ return graphemeSegmenter;
827
+ };
630
828
  var pdfRender = async (arg) => {
631
829
  const { value, pdfDoc, pdfLib, page, options, schema, _cache } = arg;
632
830
  if (!value) return;
633
831
  const { font = getDefaultFont(), colorType } = options;
634
- const [pdfFontObj, fontKitFont] = await Promise.all([embedAndGetFontObj({
832
+ const fontName = schema.fontName ? schema.fontName : getFallbackFontName(font);
833
+ const enableInlineMarkdown = isInlineMarkdownTextSchema(schema);
834
+ const pdfFontValuePromise = enableInlineMarkdown ? void 0 : embedAndGetFont({
635
835
  pdfDoc,
636
836
  font,
837
+ fontName,
637
838
  _cache
638
- }), getFontKitFont(schema.fontName, font, _cache)]);
639
- const enableInlineMarkdown = isInlineMarkdownTextSchema(schema);
839
+ });
840
+ const fontKitFont = await getFontKitFont(schema.fontName, font, _cache);
640
841
  const { fontSize, color, alignment, verticalAlignment, lineHeight, characterSpacing } = getFontProp({
641
842
  value: enableInlineMarkdown ? stripInlineMarkdown(value) : value,
642
843
  fontKitFont,
@@ -649,8 +850,6 @@ var pdfRender = async (arg) => {
649
850
  _cache
650
851
  }) : void 0
651
852
  });
652
- const fontName = schema.fontName ? schema.fontName : getFallbackFontName(font);
653
- const pdfFontValue = pdfFontObj && pdfFontObj[fontName];
654
853
  const pageHeight = page.getHeight();
655
854
  const { width, height, rotate, position: { x, y }, opacity } = convertForPdfLayoutProps({
656
855
  schema,
@@ -690,8 +889,14 @@ var pdfRender = async (arg) => {
690
889
  value,
691
890
  schema,
692
891
  font,
693
- pdfFontObj,
892
+ embedPdfFont: (fontName) => embedAndGetFont({
893
+ pdfDoc,
894
+ font,
895
+ fontName,
896
+ _cache
897
+ }),
694
898
  fontKitFont,
899
+ pdfDoc,
695
900
  page,
696
901
  pdfLib,
697
902
  _cache,
@@ -712,6 +917,8 @@ var pdfRender = async (arg) => {
712
917
  });
713
918
  return;
714
919
  }
920
+ if (!pdfFontValuePromise) throw new Error("[@pdfme/schemas] Failed to prepare PDF font for text rendering.");
921
+ const pdfFontValue = await pdfFontValuePromise;
715
922
  const firstLineTextHeight = heightOfFontAtSize(fontKitFont, fontSize);
716
923
  const descent = getFontDescentInPt(fontKitFont, fontSize);
717
924
  const halfLineHeightAdjustment = lineHeight === 0 ? 0 : (lineHeight - 1) * fontSize / 2;
@@ -722,6 +929,8 @@ var pdfRender = async (arg) => {
722
929
  fontKitFont,
723
930
  boxWidthInPt: width
724
931
  });
932
+ const needsTextWidth = alignment !== "left" || Boolean(schema.strikethrough || schema.underline);
933
+ const needsTextHeight = Boolean(schema.strikethrough || schema.underline);
725
934
  let yOffset = 0;
726
935
  if (verticalAlignment === "top") yOffset = firstLineTextHeight + halfLineHeightAdjustment;
727
936
  else {
@@ -729,11 +938,10 @@ var pdfRender = async (arg) => {
729
938
  if (verticalAlignment === "bottom") yOffset = height - otherLinesHeight + descent - halfLineHeightAdjustment;
730
939
  else if (verticalAlignment === "middle") yOffset = (height - otherLinesHeight - firstLineTextHeight + descent) / 2 + firstLineTextHeight;
731
940
  }
732
- const segmenter = new Intl.Segmenter(void 0, { granularity: "grapheme" });
733
941
  lines.forEach((line, rowIndex) => {
734
942
  const trimmed = line.replace("\n", "");
735
- const textWidth = widthOfTextAtSize(trimmed, fontKitFont, fontSize, characterSpacing);
736
- const textHeight = heightOfFontAtSize(fontKitFont, fontSize);
943
+ const textWidth = needsTextWidth ? widthOfTextAtSize(trimmed, fontKitFont, fontSize, characterSpacing) : 0;
944
+ const textHeight = needsTextHeight ? heightOfFontAtSize(fontKitFont, fontSize) : 0;
737
945
  const rowYOffset = lineHeight * fontSize * rowIndex;
738
946
  if (line === "") line = "\r\n";
739
947
  let xLine = x;
@@ -784,7 +992,7 @@ var pdfRender = async (arg) => {
784
992
  }
785
993
  let spacing = characterSpacing;
786
994
  if (alignment === "justify" && line.slice(-1) !== "\n") {
787
- const iterator = segmenter.segment(trimmed)[Symbol.iterator]();
995
+ const iterator = getGraphemeSegmenter().segment(trimmed)[Symbol.iterator]();
788
996
  const len = Array.from(iterator).length;
789
997
  spacing += (width - textWidth) / len;
790
998
  }
@@ -1261,15 +1469,28 @@ var renderInlineMarkdownReadOnly = async (arg) => {
1261
1469
  });
1262
1470
  textBlock.innerHTML = "";
1263
1471
  runs.forEach((run) => {
1264
- const span = document.createElement("span");
1265
- span.textContent = replaceUnsupportedChars(run.text, run.fontKitFont);
1472
+ const href = run.href ? normalizeLinkHref(run.href) : void 0;
1473
+ const span = href ? document.createElement("a") : document.createElement("span");
1474
+ const processedText = replaceUnsupportedChars(run.text, run.fontKitFont);
1475
+ const textDecorations = [];
1476
+ span.textContent = processedText;
1477
+ if (href) {
1478
+ const anchor = span;
1479
+ anchor.href = href;
1480
+ if (!getInternalLinkTarget(href)) {
1481
+ anchor.target = "_blank";
1482
+ anchor.rel = "noopener noreferrer";
1483
+ }
1484
+ textDecorations.push("underline");
1485
+ }
1266
1486
  if (run.fontName) span.style.fontFamily = `'${run.fontName}'`;
1267
1487
  if (run.syntheticBold) {
1268
1488
  span.style.fontWeight = "800";
1269
1489
  span.style.textShadow = SYNTHETIC_BOLD_CSS_TEXT_SHADOW;
1270
1490
  }
1271
1491
  if (run.syntheticItalic) span.style.fontStyle = "italic";
1272
- if (run.strikethrough) span.style.textDecoration = "line-through";
1492
+ if (run.strikethrough) textDecorations.push("line-through");
1493
+ if (textDecorations.length > 0) span.style.textDecoration = textDecorations.join(" ");
1273
1494
  if (run.code) {
1274
1495
  span.style.backgroundColor = CODE_BACKGROUND_COLOR;
1275
1496
  span.style.borderRadius = "2px";
@@ -1385,4 +1606,4 @@ var builtInPlugins = { Text: textSchema };
1385
1606
  //#endregion
1386
1607
  export { mapVerticalAlignToFlex as a, Formatter as c, isInlineMarkdownTextSchema as d, resolveFontVariant as f, makeElementPlainTextContentEditable as i, getExtraFormatterSchema as l, parseInlineMarkdown as m, textSchema as n, uiRender as o, escapeInlineMarkdown as p, buildStyledTextContainer as r, propPanel as s, builtInPlugins as t, pdfRender as u };
1387
1608
 
1388
- //# sourceMappingURL=builtins-C0BvXHWr.js.map
1609
+ //# sourceMappingURL=builtins-BpOyUs31.js.map