@pdfme/schemas 6.1.1-dev.5 → 6.1.1-dev.8

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 (48) hide show
  1. package/dist/{builtins-BpOyUs31.js → builtins-pN5NVCSV.js} +130 -530
  2. package/dist/builtins-pN5NVCSV.js.map +1 -0
  3. package/dist/builtins.d.ts +1 -1
  4. package/dist/builtins.js +1 -1
  5. package/dist/checkbox/index.d.ts +2 -2
  6. package/dist/dynamicLayout.d.ts +3 -0
  7. package/dist/dynamicLayout.js +20 -0
  8. package/dist/dynamicLayout.js.map +1 -0
  9. package/dist/dynamicTemplate-ByBNu75x.js +71 -0
  10. package/dist/dynamicTemplate-ByBNu75x.js.map +1 -0
  11. package/dist/{dynamicTemplate-DslOH4FZ.js → dynamicTemplate-CkrZKlg-.js} +2 -2
  12. package/dist/{dynamicTemplate-DslOH4FZ.js.map → dynamicTemplate-CkrZKlg-.js.map} +1 -1
  13. package/dist/{lists-BmAAx0lx.js → dynamicTemplate-Cy07Imb5.js} +2 -2
  14. package/dist/dynamicTemplate-Cy07Imb5.js.map +1 -0
  15. package/dist/graphics/image.d.ts +1 -1
  16. package/dist/graphics/signature.d.ts +1 -1
  17. package/dist/helper-BaUAusvL.js +40 -0
  18. package/dist/helper-BaUAusvL.js.map +1 -0
  19. package/dist/{helper-6FilIoVM.js → helper-CBd9plP_.js} +5 -2
  20. package/dist/helper-CBd9plP_.js.map +1 -0
  21. package/dist/index.js +28 -42
  22. package/dist/index.js.map +1 -1
  23. package/dist/lists.js +1 -1
  24. package/dist/measure-h-7PUE2B.js +584 -0
  25. package/dist/measure-h-7PUE2B.js.map +1 -0
  26. package/dist/multiVariableText/dynamicTemplate.d.ts +2 -0
  27. package/dist/radioGroup/index.d.ts +2 -2
  28. package/dist/select/index.d.ts +2 -2
  29. package/dist/shapes/line.d.ts +1 -1
  30. package/dist/shapes/rectAndEllipse.d.ts +1 -2
  31. package/dist/tables/helper.d.ts +4 -4
  32. package/dist/tables.js +1 -1
  33. package/dist/text/constants.d.ts +3 -0
  34. package/dist/text/dynamicTemplate.d.ts +2 -0
  35. package/dist/text/measure.d.ts +26 -0
  36. package/dist/text/overflow.d.ts +3 -0
  37. package/dist/text/types.d.ts +7 -0
  38. package/dist/texts.d.ts +4 -0
  39. package/dist/texts.js +4 -0
  40. package/dist/types.d.ts +14 -0
  41. package/dist/types.js +0 -0
  42. package/dist/utils.d.ts +1 -0
  43. package/dist/utils.js +3 -2
  44. package/dist/utils.js.map +1 -1
  45. package/package.json +16 -1
  46. package/dist/builtins-BpOyUs31.js.map +0 -1
  47. package/dist/helper-6FilIoVM.js.map +0 -1
  48. package/dist/lists-BmAAx0lx.js.map +0 -1
package/dist/lists.js CHANGED
@@ -1,2 +1,2 @@
1
- import { a as normalizeListItems, i as normalizeListItemEntries, n as calculateListLayout, o as serializeListItems, r as getListMarkers, t as getDynamicLayoutForList } from "./lists-BmAAx0lx.js";
1
+ import { a as normalizeListItems, i as normalizeListItemEntries, n as calculateListLayout, o as serializeListItems, r as getListMarkers, t as getDynamicLayoutForList } from "./dynamicTemplate-Cy07Imb5.js";
2
2
  export { calculateListLayout, getDynamicLayoutForList, getListMarkers, normalizeListItemEntries, normalizeListItems, serializeListItems };
@@ -0,0 +1,584 @@
1
+ import { A as SYNTHETIC_BOLD_OFFSET_RATIO, a as getFontKitFont, c as splitTextToSize, l as widthOfTextAtSize, o as heightOfFontAtSize, t as calculateDynamicFontSize, w as FONT_SIZE_ADJUSTMENT } from "./helper-CBd9plP_.js";
2
+ import { getDefaultFont, getFallbackFontName, mm2pt, normalizeLinkHref, pt2mm } from "@pdfme/common";
3
+ //#region src/text/inlineMarkdown.ts
4
+ var MARKDOWN_ESCAPABLE_CHARS = new Set([
5
+ "\\",
6
+ "*",
7
+ "~",
8
+ "`",
9
+ "[",
10
+ "]",
11
+ "(",
12
+ ")"
13
+ ]);
14
+ var MARKDOWN_ESCAPE_PATTERN = /[\\*~`[\]()]/g;
15
+ var MARKDOWN_UNESCAPE_PATTERN = /\\([\\*~`[\]()])/g;
16
+ 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;
17
+ var appendRun = (runs, text, style) => {
18
+ if (!text) return;
19
+ const lastRun = runs.at(-1);
20
+ if (lastRun && sameStyle(lastRun, style)) {
21
+ lastRun.text += text;
22
+ return;
23
+ }
24
+ runs.push({
25
+ text,
26
+ ...style.bold ? { bold: true } : {},
27
+ ...style.italic ? { italic: true } : {},
28
+ ...style.strikethrough ? { strikethrough: true } : {},
29
+ ...style.code ? { code: true } : {},
30
+ ...style.href ? { href: style.href } : {}
31
+ });
32
+ };
33
+ var findClosingDelimiter = (value, delimiter, from) => {
34
+ for (let i = from; i < value.length; i++) {
35
+ if (value[i] === "\\") {
36
+ i += 1;
37
+ continue;
38
+ }
39
+ if (delimiter !== "`" && value[i] === "`") {
40
+ const codeEnd = findClosingDelimiter(value, "`", i + 1);
41
+ if (codeEnd === -1) continue;
42
+ i = codeEnd;
43
+ continue;
44
+ }
45
+ if (value.startsWith(delimiter, i)) return i;
46
+ }
47
+ return -1;
48
+ };
49
+ var getDelimiter = (value, index) => {
50
+ if (value[index] === "`") return "`";
51
+ if (value.startsWith("***", index)) return "***";
52
+ if (value.startsWith("**", index)) return "**";
53
+ if (value.startsWith("~~", index)) return "~~";
54
+ if (value[index] === "*") return "*";
55
+ return "";
56
+ };
57
+ var findLinkLabelEnd = (value, from, to) => {
58
+ for (let index = from; index < to; index += 1) {
59
+ if (value[index] === "\\") {
60
+ index += 1;
61
+ continue;
62
+ }
63
+ if (value[index] === "]") return index;
64
+ }
65
+ return -1;
66
+ };
67
+ var findLinkDestinationEnd = (value, from, to) => {
68
+ let depth = 0;
69
+ for (let index = from; index < to; index += 1) {
70
+ if (value[index] === "\\") {
71
+ index += 1;
72
+ continue;
73
+ }
74
+ if (value[index] === "(") {
75
+ depth += 1;
76
+ continue;
77
+ }
78
+ if (value[index] === ")") {
79
+ if (depth === 0) return index;
80
+ depth -= 1;
81
+ }
82
+ }
83
+ return -1;
84
+ };
85
+ var parseLinkAt = (value, index, to) => {
86
+ if (value[index] !== "[") return void 0;
87
+ const labelEnd = findLinkLabelEnd(value, index + 1, to);
88
+ if (labelEnd === -1 || value[labelEnd + 1] !== "(") return void 0;
89
+ const destinationStart = labelEnd + 2;
90
+ const destinationEnd = findLinkDestinationEnd(value, destinationStart, to);
91
+ if (destinationEnd === -1) return void 0;
92
+ const safeHref = normalizeLinkHref(value.slice(destinationStart, destinationEnd).replace(MARKDOWN_UNESCAPE_PATTERN, "$1"));
93
+ if (!safeHref) return void 0;
94
+ return {
95
+ labelStart: index + 1,
96
+ labelEnd,
97
+ href: safeHref,
98
+ end: destinationEnd + 1
99
+ };
100
+ };
101
+ var mergeStyle = (style, delimiter) => {
102
+ if (delimiter === "***") return {
103
+ ...style,
104
+ bold: true,
105
+ italic: true
106
+ };
107
+ if (delimiter === "**") return {
108
+ ...style,
109
+ bold: true
110
+ };
111
+ if (delimiter === "*") return {
112
+ ...style,
113
+ italic: true
114
+ };
115
+ if (delimiter === "~~") return {
116
+ ...style,
117
+ strikethrough: true
118
+ };
119
+ return style;
120
+ };
121
+ var parseRange = (value, from, to, style) => {
122
+ const runs = [];
123
+ let buffer = "";
124
+ const flush = () => {
125
+ appendRun(runs, buffer, style);
126
+ buffer = "";
127
+ };
128
+ for (let index = from; index < to; index++) {
129
+ const char = value[index];
130
+ if (char === "\\" && index + 1 < to && MARKDOWN_ESCAPABLE_CHARS.has(value[index + 1])) {
131
+ buffer += value[index + 1];
132
+ index += 1;
133
+ continue;
134
+ }
135
+ const link = style.href ? void 0 : parseLinkAt(value, index, to);
136
+ if (link) {
137
+ flush();
138
+ parseRange(value, link.labelStart, link.labelEnd, {
139
+ ...style,
140
+ href: link.href
141
+ }).forEach((run) => appendRun(runs, run.text, run));
142
+ index = link.end - 1;
143
+ continue;
144
+ }
145
+ const delimiter = getDelimiter(value, index);
146
+ if (!delimiter) {
147
+ buffer += char;
148
+ continue;
149
+ }
150
+ const closingIndex = findClosingDelimiter(value, delimiter, index + delimiter.length);
151
+ if (closingIndex === -1 || closingIndex + delimiter.length > to) {
152
+ buffer += char;
153
+ continue;
154
+ }
155
+ flush();
156
+ if (delimiter === "`") appendRun(runs, value.slice(index + 1, closingIndex).replace(MARKDOWN_UNESCAPE_PATTERN, "$1"), {
157
+ ...style,
158
+ code: true
159
+ });
160
+ else parseRange(value, index + delimiter.length, closingIndex, mergeStyle(style, delimiter)).forEach((run) => appendRun(runs, run.text, run));
161
+ index = closingIndex + delimiter.length - 1;
162
+ }
163
+ flush();
164
+ return runs;
165
+ };
166
+ var parseInlineMarkdown = (value) => {
167
+ if (!value) return [];
168
+ return parseRange(value, 0, value.length, {});
169
+ };
170
+ var escapeInlineMarkdown = (value) => value.replace(MARKDOWN_ESCAPE_PATTERN, (char) => `\\${char}`);
171
+ var stripInlineMarkdown = (value) => parseInlineMarkdown(value).map((run) => run.text).join("");
172
+ //#endregion
173
+ //#region src/text/richText.ts
174
+ var richTextWordSegmenter = new Intl.Segmenter(void 0, { granularity: "word" });
175
+ var richTextGraphemeSegmenter = new Intl.Segmenter(void 0, { granularity: "grapheme" });
176
+ var getBaseFontName = (schema, font) => schema.fontName && font[schema.fontName] ? schema.fontName : getFallbackFontName(font);
177
+ var getLoadedFontName = (font, fontName) => fontName && font[fontName] ? fontName : void 0;
178
+ var isInlineMarkdownTextSchema = (schema) => schema.textFormat === "inline-markdown" && !(schema.type === "text" && schema.readOnly !== true);
179
+ var resolveFontVariant = (run, schema, font) => {
180
+ const baseFontName = getBaseFontName(schema, font);
181
+ const variants = schema.fontVariants ?? {};
182
+ const fallback = schema.fontVariantFallback ?? "synthetic";
183
+ let fontName = baseFontName;
184
+ let needsBold = Boolean(run.bold);
185
+ let needsItalic = Boolean(run.italic);
186
+ if (run.code) fontName = getLoadedFontName(font, variants.code) ?? baseFontName;
187
+ else if (run.bold && run.italic) {
188
+ const boldItalic = getLoadedFontName(font, variants.boldItalic);
189
+ const italic = getLoadedFontName(font, variants.italic);
190
+ const bold = getLoadedFontName(font, variants.bold);
191
+ if (boldItalic) {
192
+ fontName = boldItalic;
193
+ needsBold = false;
194
+ needsItalic = false;
195
+ } else if (italic) {
196
+ fontName = italic;
197
+ needsItalic = false;
198
+ } else if (bold) {
199
+ fontName = bold;
200
+ needsBold = false;
201
+ }
202
+ } else if (run.bold) {
203
+ const bold = getLoadedFontName(font, variants.bold);
204
+ if (bold) {
205
+ fontName = bold;
206
+ needsBold = false;
207
+ }
208
+ } else if (run.italic) {
209
+ const italic = getLoadedFontName(font, variants.italic);
210
+ if (italic) {
211
+ fontName = italic;
212
+ needsItalic = false;
213
+ }
214
+ }
215
+ if ((needsBold || needsItalic || run.code && !getLoadedFontName(font, variants.code)) && fallback === "error") throw new Error(`[@pdfme/schemas] Missing font variant for markdown text in field "${schema.name}".`);
216
+ return {
217
+ fontName,
218
+ syntheticBold: fallback !== "plain" && needsBold,
219
+ syntheticItalic: fallback !== "plain" && needsItalic
220
+ };
221
+ };
222
+ var resolveRichTextRuns = async (arg) => {
223
+ const { runs, schema, font, _cache } = arg;
224
+ const fontKitCache = /* @__PURE__ */ new Map();
225
+ const getResolvedFontKitFont = async (fontName) => {
226
+ const cached = fontKitCache.get(fontName);
227
+ if (cached) return cached;
228
+ const fontKitFont = await getFontKitFont(fontName, font, _cache);
229
+ fontKitCache.set(fontName, fontKitFont);
230
+ return fontKitFont;
231
+ };
232
+ return Promise.all(runs.map(async (run) => {
233
+ const resolution = resolveFontVariant(run, schema, font);
234
+ return {
235
+ ...run,
236
+ ...resolution,
237
+ fontKitFont: await getResolvedFontKitFont(resolution.fontName)
238
+ };
239
+ }));
240
+ };
241
+ var measureRunText = (run, text, fontSize, characterSpacing) => {
242
+ const syntheticBoldWidth = run.syntheticBold ? fontSize * SYNTHETIC_BOLD_OFFSET_RATIO * 2 : 0;
243
+ const syntheticItalicWidth = run.syntheticItalic ? heightOfFontAtSize(run.fontKitFont, fontSize) * Math.tan(12 * Math.PI / 180) : 0;
244
+ return widthOfTextAtSize(text, run.fontKitFont, fontSize, characterSpacing) + syntheticBoldWidth + syntheticItalicWidth;
245
+ };
246
+ var createLine = () => ({
247
+ runs: [],
248
+ width: 0,
249
+ hardBreak: false
250
+ });
251
+ var pushRunToLine = (line, run, text, fontSize, characterSpacing) => {
252
+ if (!text) return;
253
+ const width = measureRunText(run, text, fontSize, characterSpacing);
254
+ if (line.runs.length > 0) line.width += characterSpacing;
255
+ line.runs.push({
256
+ ...run,
257
+ text,
258
+ width
259
+ });
260
+ line.width += width;
261
+ };
262
+ var measurePiecesWidth = (pieces, fontSize, characterSpacing) => {
263
+ let width = 0;
264
+ let hasText = false;
265
+ pieces.forEach((piece) => {
266
+ if (!piece.text) return;
267
+ if (hasText) width += characterSpacing;
268
+ width += measureRunText(piece.run, piece.text, fontSize, characterSpacing);
269
+ hasText = true;
270
+ });
271
+ return width;
272
+ };
273
+ var sliceRunPieces = (pieces, startIndex, endIndex) => {
274
+ const result = [];
275
+ let offset = 0;
276
+ pieces.forEach((piece) => {
277
+ const pieceStart = offset;
278
+ const pieceEnd = pieceStart + piece.text.length;
279
+ const sliceStart = Math.max(startIndex, pieceStart);
280
+ const sliceEnd = Math.min(endIndex, pieceEnd);
281
+ if (sliceStart < sliceEnd) result.push({
282
+ run: piece.run,
283
+ text: piece.text.slice(sliceStart - pieceStart, sliceEnd - pieceStart)
284
+ });
285
+ offset = pieceEnd;
286
+ });
287
+ return result;
288
+ };
289
+ var segmentRunPiecesByWord = (runs, onSegment, onHardBreak) => {
290
+ let paragraphPieces = [];
291
+ const flushParagraph = () => {
292
+ if (paragraphPieces.length === 0) return;
293
+ const paragraphText = paragraphPieces.map((piece) => piece.text).join("");
294
+ Array.from(richTextWordSegmenter.segment(paragraphText), ({ segment, index }) => {
295
+ const pieces = sliceRunPieces(paragraphPieces, index, index + segment.length);
296
+ if (pieces.length > 0) onSegment(pieces);
297
+ });
298
+ paragraphPieces = [];
299
+ };
300
+ runs.forEach((run) => {
301
+ run.text.split(/(\r\n|\r|\n)/).forEach((part) => {
302
+ if (part === "\r\n" || part === "\r" || part === "\n") {
303
+ flushParagraph();
304
+ onHardBreak();
305
+ return;
306
+ }
307
+ if (part) paragraphPieces.push({
308
+ run,
309
+ text: part
310
+ });
311
+ });
312
+ });
313
+ flushParagraph();
314
+ };
315
+ var splitIntoGraphemes = (value) => Array.from(richTextGraphemeSegmenter.segment(value), ({ segment }) => segment);
316
+ var countRichTextLineGraphemes = (line) => splitIntoGraphemes(line.runs.map((run) => run.text).join("")).length;
317
+ var layoutRichTextLines = (arg) => {
318
+ const { runs, fontSize, characterSpacing, boxWidthInPt } = arg;
319
+ const lines = [];
320
+ let currentLine = createLine();
321
+ const pushCurrentLine = (hardBreak) => {
322
+ currentLine.hardBreak = hardBreak;
323
+ lines.push(currentLine);
324
+ currentLine = createLine();
325
+ };
326
+ const pushPiecesToLine = (pieces) => {
327
+ pieces.forEach((piece) => {
328
+ pushRunToLine(currentLine, piece.run, piece.text, fontSize, characterSpacing);
329
+ });
330
+ };
331
+ const pushOversizedText = (run, text) => {
332
+ let remainingText = text;
333
+ while (remainingText.length > 0) {
334
+ const pendingSpacing = currentLine.runs.length > 0 ? characterSpacing : 0;
335
+ const remainingWidth = Math.max(boxWidthInPt - currentLine.width - pendingSpacing, 0);
336
+ const remainingTextWidth = measureRunText(run, remainingText, fontSize, characterSpacing);
337
+ if (remainingTextWidth <= remainingWidth || currentLine.runs.length === 0 && remainingTextWidth <= boxWidthInPt) {
338
+ pushRunToLine(currentLine, run, remainingText, fontSize, characterSpacing);
339
+ return;
340
+ }
341
+ if (currentLine.runs.length > 0 && remainingTextWidth <= boxWidthInPt) {
342
+ pushCurrentLine(false);
343
+ continue;
344
+ }
345
+ const graphemes = splitIntoGraphemes(remainingText);
346
+ let fittingText = "";
347
+ let fittingLength = 0;
348
+ for (const grapheme of graphemes) {
349
+ const candidate = fittingText + grapheme;
350
+ const candidateWidth = measureRunText(run, candidate, fontSize, characterSpacing);
351
+ const maxWidth = currentLine.runs.length === 0 ? boxWidthInPt : remainingWidth;
352
+ if (candidateWidth > maxWidth) {
353
+ if (fittingText) break;
354
+ if (currentLine.runs.length > 0) break;
355
+ }
356
+ fittingText = candidate;
357
+ fittingLength += grapheme.length;
358
+ if (candidateWidth > maxWidth) break;
359
+ }
360
+ if (!fittingText) {
361
+ pushCurrentLine(false);
362
+ continue;
363
+ }
364
+ pushRunToLine(currentLine, run, fittingText, fontSize, characterSpacing);
365
+ remainingText = remainingText.slice(fittingLength);
366
+ if (remainingText.length > 0) pushCurrentLine(false);
367
+ }
368
+ };
369
+ const pushSegment = (pieces) => {
370
+ const segmentWidth = measurePiecesWidth(pieces, fontSize, characterSpacing);
371
+ const pendingSpacing = currentLine.runs.length > 0 ? characterSpacing : 0;
372
+ if (segmentWidth <= Math.max(boxWidthInPt - currentLine.width - pendingSpacing, 0) || currentLine.runs.length === 0 && segmentWidth <= boxWidthInPt) {
373
+ pushPiecesToLine(pieces);
374
+ return;
375
+ }
376
+ if (currentLine.runs.length > 0) {
377
+ pushCurrentLine(false);
378
+ if (segmentWidth <= boxWidthInPt) {
379
+ pushPiecesToLine(pieces);
380
+ return;
381
+ }
382
+ }
383
+ pieces.forEach((piece) => pushOversizedText(piece.run, piece.text));
384
+ };
385
+ segmentRunPiecesByWord(runs, pushSegment, () => pushCurrentLine(true));
386
+ if (currentLine.runs.length > 0 || lines.length === 0) pushCurrentLine(false);
387
+ return lines;
388
+ };
389
+ var measureParagraphWidths = (runs, fontSize, characterSpacing) => {
390
+ const widths = [];
391
+ let paragraphPieces = [];
392
+ const pushWidth = () => {
393
+ widths.push(measurePiecesWidth(paragraphPieces, fontSize, characterSpacing));
394
+ paragraphPieces = [];
395
+ };
396
+ runs.forEach((run) => {
397
+ run.text.split(/(\r\n|\r|\n)/).forEach((part) => {
398
+ if (part === "\r\n" || part === "\r" || part === "\n") {
399
+ pushWidth();
400
+ return;
401
+ }
402
+ if (part) paragraphPieces.push({
403
+ run,
404
+ text: part
405
+ });
406
+ });
407
+ });
408
+ pushWidth();
409
+ return widths;
410
+ };
411
+ var getLineHeightAtSize = (line, fontSize) => {
412
+ if (line.runs.length === 0) return fontSize;
413
+ return Math.max(...line.runs.map((run) => heightOfFontAtSize(run.fontKitFont, fontSize)));
414
+ };
415
+ var calculateDynamicRichTextFontSize = async (arg) => {
416
+ const { value, schema, font, _cache, startingFontSize } = arg;
417
+ const { fontSize: schemaFontSize, dynamicFontSize: dynamicFontSizeSetting, characterSpacing: schemaCharacterSpacing, width: boxWidth, height: boxHeight, lineHeight = 1 } = schema;
418
+ const fontSize = startingFontSize || schemaFontSize || 13;
419
+ if (!dynamicFontSizeSetting) return fontSize;
420
+ if (dynamicFontSizeSetting.max < dynamicFontSizeSetting.min) return fontSize;
421
+ const resolvedRuns = await resolveRichTextRuns({
422
+ runs: parseInlineMarkdown(value),
423
+ schema,
424
+ font,
425
+ _cache
426
+ });
427
+ const characterSpacing = schemaCharacterSpacing ?? 0;
428
+ const dynamicFontFit = dynamicFontSizeSetting.fit ?? "vertical";
429
+ const boxWidthInPt = mm2pt(boxWidth);
430
+ let dynamicFontSize = fontSize;
431
+ if (dynamicFontSize < dynamicFontSizeSetting.min) dynamicFontSize = dynamicFontSizeSetting.min;
432
+ else if (dynamicFontSize > dynamicFontSizeSetting.max) dynamicFontSize = dynamicFontSizeSetting.max;
433
+ const calculateConstraints = (size) => {
434
+ let totalWidthInMm = 0;
435
+ let totalHeightInMm = 0;
436
+ layoutRichTextLines({
437
+ runs: resolvedRuns,
438
+ fontSize: size,
439
+ characterSpacing,
440
+ boxWidthInPt
441
+ }).forEach((line, lineIndex) => {
442
+ if (dynamicFontFit === "vertical") totalWidthInMm = Math.max(totalWidthInMm, pt2mm(line.width));
443
+ if (lineIndex === 0) totalHeightInMm += pt2mm(getLineHeightAtSize(line, size) * lineHeight);
444
+ else totalHeightInMm += pt2mm(size * lineHeight);
445
+ });
446
+ if (dynamicFontFit === "horizontal") measureParagraphWidths(resolvedRuns, size, characterSpacing).forEach((paragraphWidth) => {
447
+ totalWidthInMm = Math.max(totalWidthInMm, pt2mm(paragraphWidth));
448
+ });
449
+ return {
450
+ totalWidthInMm,
451
+ totalHeightInMm
452
+ };
453
+ };
454
+ const shouldFontGrowToFit = (totalWidthInMm, totalHeightInMm) => {
455
+ if (dynamicFontSize >= dynamicFontSizeSetting.max) return false;
456
+ if (dynamicFontFit === "horizontal") return totalWidthInMm < boxWidth;
457
+ return totalHeightInMm < boxHeight;
458
+ };
459
+ const shouldFontShrinkToFit = (totalWidthInMm, totalHeightInMm) => {
460
+ if (dynamicFontSize <= dynamicFontSizeSetting.min || dynamicFontSize <= 0) return false;
461
+ return totalWidthInMm > boxWidth || totalHeightInMm > boxHeight;
462
+ };
463
+ let { totalWidthInMm, totalHeightInMm } = calculateConstraints(dynamicFontSize);
464
+ while (shouldFontGrowToFit(totalWidthInMm, totalHeightInMm)) {
465
+ dynamicFontSize += FONT_SIZE_ADJUSTMENT;
466
+ const { totalWidthInMm: newWidth, totalHeightInMm: newHeight } = calculateConstraints(dynamicFontSize);
467
+ if (newHeight < boxHeight) {
468
+ totalWidthInMm = newWidth;
469
+ totalHeightInMm = newHeight;
470
+ } else {
471
+ dynamicFontSize -= FONT_SIZE_ADJUSTMENT;
472
+ break;
473
+ }
474
+ }
475
+ while (shouldFontShrinkToFit(totalWidthInMm, totalHeightInMm)) {
476
+ dynamicFontSize -= FONT_SIZE_ADJUSTMENT;
477
+ ({totalWidthInMm, totalHeightInMm} = calculateConstraints(dynamicFontSize));
478
+ }
479
+ return dynamicFontSize;
480
+ };
481
+ //#endregion
482
+ //#region src/text/measure.ts
483
+ var applyTextLineRange = (lines, range) => {
484
+ if (!range) return lines;
485
+ return lines.slice(range.start, range.end ?? lines.length);
486
+ };
487
+ var plainTextLinesToValue = (lines) => lines.map((line) => line.replace(/[\r\n]+$/g, "")).join("\n");
488
+ var splitReplacementTextToLines = (value) => {
489
+ const lines = [];
490
+ let start = 0;
491
+ for (let i = 0; i < value.length; i += 1) {
492
+ const charCode = value.charCodeAt(i);
493
+ if (charCode !== 10 && charCode !== 13) continue;
494
+ lines.push(value.slice(start, i));
495
+ if (charCode === 13 && value.charCodeAt(i + 1) === 10) i += 1;
496
+ start = i + 1;
497
+ }
498
+ lines.push(value.slice(start));
499
+ return lines;
500
+ };
501
+ var measureTextLines = async ({ value, schema, font = getDefaultFont(), _cache = /* @__PURE__ */ new Map(), ignoreDynamicFontSize = false }) => {
502
+ const fontSize = schema.fontSize ?? 13;
503
+ const lineHeight = schema.lineHeight ?? 1;
504
+ const characterSpacing = schema.characterSpacing ?? 0;
505
+ const boxWidthInPt = mm2pt(schema.width);
506
+ if (isInlineMarkdownTextSchema(schema)) {
507
+ const resolvedRuns = await resolveRichTextRuns({
508
+ runs: parseInlineMarkdown(value),
509
+ schema,
510
+ font,
511
+ _cache
512
+ });
513
+ const resolvedFontSize = schema.dynamicFontSize && schema.height > 0 && !ignoreDynamicFontSize ? await calculateDynamicRichTextFontSize({
514
+ value,
515
+ schema,
516
+ font,
517
+ _cache
518
+ }) : fontSize;
519
+ const lines = layoutRichTextLines({
520
+ runs: resolvedRuns,
521
+ fontSize: resolvedFontSize,
522
+ characterSpacing,
523
+ boxWidthInPt
524
+ });
525
+ return {
526
+ lines: lines.map((line) => line.runs.map((run) => run.text).join("")),
527
+ lineHeights: measureRichTextLineHeights(lines, resolvedFontSize, lineHeight)
528
+ };
529
+ }
530
+ const fontKitFont = await getFontKitFont(schema.fontName, font, _cache);
531
+ const resolvedFontSize = schema.dynamicFontSize && schema.height > 0 && !ignoreDynamicFontSize ? calculateDynamicFontSize({
532
+ textSchema: schema,
533
+ fontKitFont,
534
+ value
535
+ }) : fontSize;
536
+ const lines = splitTextToSize({
537
+ value,
538
+ characterSpacing,
539
+ fontSize: resolvedFontSize,
540
+ fontKitFont,
541
+ boxWidthInPt
542
+ });
543
+ return {
544
+ lines,
545
+ lineHeights: measurePlainTextLineHeights(lines, fontKitFont, resolvedFontSize, lineHeight)
546
+ };
547
+ };
548
+ var mergeTextLineRangeValue = async ({ value, replacement, schema, font = getDefaultFont(), _cache = /* @__PURE__ */ new Map() }) => {
549
+ if (!schema.__textLineRange) return replacement;
550
+ const { lines } = await measureTextLines({
551
+ value,
552
+ schema,
553
+ font,
554
+ _cache,
555
+ ignoreDynamicFontSize: true
556
+ });
557
+ const { start, end = lines.length } = schema.__textLineRange;
558
+ const nextLines = [...lines];
559
+ nextLines.splice(start, end - start, ...splitReplacementTextToLines(replacement));
560
+ return plainTextLinesToValue(nextLines);
561
+ };
562
+ var measureTextHeight = async (args) => {
563
+ const { lineHeights } = await measureTextLines(args);
564
+ return sumLineHeights(lineHeights);
565
+ };
566
+ var sumLineHeights = (lineHeights) => lineHeights.reduce((sum, height) => sum + height, 0);
567
+ var measurePlainTextLineHeights = (lines, fontKitFont, fontSize, lineHeight) => {
568
+ if (lines.length === 0) return [];
569
+ const firstLineHeight = heightOfFontAtSize(fontKitFont, fontSize) * lineHeight;
570
+ const otherLineHeight = fontSize * lineHeight;
571
+ return lines.map((_, index) => pt2mm(index === 0 ? firstLineHeight : otherLineHeight));
572
+ };
573
+ var measureRichTextLineHeights = (lines, fontSize, lineHeight) => {
574
+ if (lines.length === 0) return [];
575
+ return lines.map((line, index) => pt2mm((index === 0 ? getRichTextLineHeight(line, fontSize) : fontSize) * lineHeight));
576
+ };
577
+ var getRichTextLineHeight = (line, fontSize) => {
578
+ if (line.runs.length === 0) return fontSize;
579
+ return Math.max(...line.runs.map((run) => heightOfFontAtSize(run.fontKitFont, fontSize)));
580
+ };
581
+ //#endregion
582
+ export { plainTextLinesToValue as a, countRichTextLineGraphemes as c, resolveFontVariant as d, resolveRichTextRuns as f, stripInlineMarkdown as h, mergeTextLineRangeValue as i, isInlineMarkdownTextSchema as l, parseInlineMarkdown as m, measureTextHeight as n, sumLineHeights as o, escapeInlineMarkdown as p, measureTextLines as r, calculateDynamicRichTextFontSize as s, applyTextLineRange as t, layoutRichTextLines as u };
583
+
584
+ //# sourceMappingURL=measure-h-7PUE2B.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"measure-h-7PUE2B.js","names":[],"sources":["../src/text/inlineMarkdown.ts","../src/text/richText.ts","../src/text/measure.ts"],"sourcesContent":["import { normalizeLinkHref } from '@pdfme/common';\nimport type { RichTextRun } from './types.js';\n\ntype InlineStyle = Omit<RichTextRun, 'text'>;\n\nconst MARKDOWN_ESCAPABLE_CHARS = new Set(['\\\\', '*', '~', '`', '[', ']', '(', ')']);\nconst MARKDOWN_ESCAPE_PATTERN = /[\\\\*~`[\\]()]/g;\nconst MARKDOWN_UNESCAPE_PATTERN = /\\\\([\\\\*~`[\\]()])/g;\n\nconst sameStyle = (a: InlineStyle, b: InlineStyle) =>\n Boolean(a.bold) === Boolean(b.bold) &&\n Boolean(a.italic) === Boolean(b.italic) &&\n Boolean(a.strikethrough) === Boolean(b.strikethrough) &&\n Boolean(a.code) === Boolean(b.code) &&\n a.href === b.href;\n\nconst appendRun = (runs: RichTextRun[], text: string, style: InlineStyle) => {\n if (!text) return;\n\n const lastRun = runs.at(-1);\n if (lastRun && sameStyle(lastRun, style)) {\n lastRun.text += text;\n return;\n }\n\n runs.push({\n text,\n ...(style.bold ? { bold: true } : {}),\n ...(style.italic ? { italic: true } : {}),\n ...(style.strikethrough ? { strikethrough: true } : {}),\n ...(style.code ? { code: true } : {}),\n ...(style.href ? { href: style.href } : {}),\n });\n};\n\nconst findClosingDelimiter = (value: string, delimiter: string, from: number): number => {\n for (let i = from; i < value.length; i++) {\n if (value[i] === '\\\\') {\n i += 1;\n continue;\n }\n\n if (delimiter !== '`' && value[i] === '`') {\n const codeEnd = findClosingDelimiter(value, '`', i + 1);\n if (codeEnd === -1) continue;\n i = codeEnd;\n continue;\n }\n\n if (value.startsWith(delimiter, i)) {\n return i;\n }\n }\n\n return -1;\n};\n\nconst getDelimiter = (value: string, index: number) => {\n if (value[index] === '`') return '`';\n if (value.startsWith('***', index)) return '***';\n if (value.startsWith('**', index)) return '**';\n if (value.startsWith('~~', index)) return '~~';\n if (value[index] === '*') return '*';\n return '';\n};\n\nconst findLinkLabelEnd = (value: string, from: number, to: number): number => {\n for (let index = from; index < to; index += 1) {\n if (value[index] === '\\\\') {\n index += 1;\n continue;\n }\n\n if (value[index] === ']') return index;\n }\n\n return -1;\n};\n\nconst findLinkDestinationEnd = (value: string, from: number, to: number): number => {\n let depth = 0;\n\n for (let index = from; index < to; index += 1) {\n if (value[index] === '\\\\') {\n index += 1;\n continue;\n }\n\n if (value[index] === '(') {\n depth += 1;\n continue;\n }\n\n if (value[index] === ')') {\n if (depth === 0) return index;\n depth -= 1;\n }\n }\n\n return -1;\n};\n\nconst parseLinkAt = (value: string, index: number, to: number) => {\n if (value[index] !== '[') return undefined;\n\n const labelEnd = findLinkLabelEnd(value, index + 1, to);\n if (labelEnd === -1 || value[labelEnd + 1] !== '(') return undefined;\n\n const destinationStart = labelEnd + 2;\n const destinationEnd = findLinkDestinationEnd(value, destinationStart, to);\n if (destinationEnd === -1) return undefined;\n\n const href = value\n .slice(destinationStart, destinationEnd)\n .replace(MARKDOWN_UNESCAPE_PATTERN, '$1');\n const safeHref = normalizeLinkHref(href);\n if (!safeHref) return undefined;\n\n return {\n labelStart: index + 1,\n labelEnd,\n href: safeHref,\n end: destinationEnd + 1,\n };\n};\n\nconst mergeStyle = (style: InlineStyle, delimiter: string): InlineStyle => {\n if (delimiter === '***') {\n return { ...style, bold: true, italic: true };\n }\n if (delimiter === '**') {\n return { ...style, bold: true };\n }\n if (delimiter === '*') {\n return { ...style, italic: true };\n }\n if (delimiter === '~~') {\n return { ...style, strikethrough: true };\n }\n return style;\n};\n\nconst parseRange = (value: string, from: number, to: number, style: InlineStyle): RichTextRun[] => {\n const runs: RichTextRun[] = [];\n let buffer = '';\n\n const flush = () => {\n appendRun(runs, buffer, style);\n buffer = '';\n };\n\n for (let index = from; index < to; index++) {\n const char = value[index];\n\n if (char === '\\\\' && index + 1 < to && MARKDOWN_ESCAPABLE_CHARS.has(value[index + 1])) {\n buffer += value[index + 1];\n index += 1;\n continue;\n }\n\n const link = style.href ? undefined : parseLinkAt(value, index, to);\n if (link) {\n flush();\n const nestedRuns = parseRange(value, link.labelStart, link.labelEnd, {\n ...style,\n href: link.href,\n });\n nestedRuns.forEach((run) => appendRun(runs, run.text, run));\n index = link.end - 1;\n continue;\n }\n\n const delimiter = getDelimiter(value, index);\n if (!delimiter) {\n buffer += char;\n continue;\n }\n\n const closingIndex = findClosingDelimiter(value, delimiter, index + delimiter.length);\n if (closingIndex === -1 || closingIndex + delimiter.length > to) {\n buffer += char;\n continue;\n }\n\n flush();\n\n if (delimiter === '`') {\n appendRun(\n runs,\n value.slice(index + 1, closingIndex).replace(MARKDOWN_UNESCAPE_PATTERN, '$1'),\n { ...style, code: true },\n );\n } else {\n const nestedRuns = parseRange(\n value,\n index + delimiter.length,\n closingIndex,\n mergeStyle(style, delimiter),\n );\n nestedRuns.forEach((run) => appendRun(runs, run.text, run));\n }\n\n index = closingIndex + delimiter.length - 1;\n }\n\n flush();\n return runs;\n};\n\nexport const parseInlineMarkdown = (value: string): RichTextRun[] => {\n if (!value) return [];\n return parseRange(value, 0, value.length, {});\n};\n\nexport const escapeInlineMarkdown = (value: string): string =>\n value.replace(MARKDOWN_ESCAPE_PATTERN, (char) => `\\\\${char}`);\n\nexport const stripInlineMarkdown = (value: string): string =>\n parseInlineMarkdown(value)\n .map((run) => run.text)\n .join('');\n","import { getFallbackFontName, mm2pt, pt2mm, type Font } from '@pdfme/common';\nimport type { Font as FontKitFont } from 'fontkit';\nimport {\n DEFAULT_CHARACTER_SPACING,\n DEFAULT_DYNAMIC_FIT,\n DEFAULT_FONT_SIZE,\n DEFAULT_LINE_HEIGHT,\n DEFAULT_FONT_VARIANT_FALLBACK,\n DYNAMIC_FIT_HORIZONTAL,\n DYNAMIC_FIT_VERTICAL,\n FONT_SIZE_ADJUSTMENT,\n FONT_VARIANT_FALLBACK_ERROR,\n FONT_VARIANT_FALLBACK_PLAIN,\n SYNTHETIC_BOLD_OFFSET_RATIO,\n SYNTHETIC_BOLD_PDF_EXTRA_DRAWS,\n SYNTHETIC_ITALIC_SKEW_DEGREES,\n TEXT_FORMAT_INLINE_MARKDOWN,\n} from './constants.js';\nimport { getFontKitFont, heightOfFontAtSize, widthOfTextAtSize } from './helper.js';\nimport { parseInlineMarkdown } from './inlineMarkdown.js';\nimport type { RichTextRun, TextSchema } from './types.js';\n\nexport type ResolvedRichTextRun = RichTextRun & {\n fontName: string;\n fontKitFont: FontKitFont;\n syntheticBold: boolean;\n syntheticItalic: boolean;\n};\n\nexport type RichTextLineRun = ResolvedRichTextRun & {\n width: number;\n};\n\nexport type RichTextLine = {\n runs: RichTextLineRun[];\n width: number;\n hardBreak: boolean;\n};\n\ntype FontVariantResolution = {\n fontName: string;\n syntheticBold: boolean;\n syntheticItalic: boolean;\n};\n\ntype RichTextRunPiece = {\n run: ResolvedRichTextRun;\n text: string;\n};\n\nconst richTextWordSegmenter = new Intl.Segmenter(undefined, { granularity: 'word' });\nconst richTextGraphemeSegmenter = new Intl.Segmenter(undefined, { granularity: 'grapheme' });\n\nconst getBaseFontName = (schema: TextSchema, font: Font) =>\n schema.fontName && font[schema.fontName] ? schema.fontName : getFallbackFontName(font);\n\nconst getLoadedFontName = (font: Font, fontName?: string) =>\n fontName && font[fontName] ? fontName : undefined;\n\nexport const isInlineMarkdownTextSchema = (schema: TextSchema) =>\n schema.textFormat === TEXT_FORMAT_INLINE_MARKDOWN &&\n !(schema.type === 'text' && schema.readOnly !== true);\n\nexport const resolveFontVariant = (\n run: RichTextRun,\n schema: TextSchema,\n font: Font,\n): FontVariantResolution => {\n const baseFontName = getBaseFontName(schema, font);\n const variants = schema.fontVariants ?? {};\n const fallback = schema.fontVariantFallback ?? DEFAULT_FONT_VARIANT_FALLBACK;\n\n let fontName = baseFontName;\n let needsBold = Boolean(run.bold);\n let needsItalic = Boolean(run.italic);\n\n if (run.code) {\n fontName = getLoadedFontName(font, variants.code) ?? baseFontName;\n } else if (run.bold && run.italic) {\n const boldItalic = getLoadedFontName(font, variants.boldItalic);\n const italic = getLoadedFontName(font, variants.italic);\n const bold = getLoadedFontName(font, variants.bold);\n\n if (boldItalic) {\n fontName = boldItalic;\n needsBold = false;\n needsItalic = false;\n } else if (italic) {\n fontName = italic;\n needsItalic = false;\n } else if (bold) {\n fontName = bold;\n needsBold = false;\n }\n } else if (run.bold) {\n const bold = getLoadedFontName(font, variants.bold);\n if (bold) {\n fontName = bold;\n needsBold = false;\n }\n } else if (run.italic) {\n const italic = getLoadedFontName(font, variants.italic);\n if (italic) {\n fontName = italic;\n needsItalic = false;\n }\n }\n\n if (\n (needsBold || needsItalic || (run.code && !getLoadedFontName(font, variants.code))) &&\n fallback === FONT_VARIANT_FALLBACK_ERROR\n ) {\n throw new Error(\n `[@pdfme/schemas] Missing font variant for markdown text in field \"${schema.name}\".`,\n );\n }\n\n return {\n fontName,\n syntheticBold: fallback !== FONT_VARIANT_FALLBACK_PLAIN && needsBold,\n syntheticItalic: fallback !== FONT_VARIANT_FALLBACK_PLAIN && needsItalic,\n };\n};\n\nexport const resolveRichTextRuns = async (arg: {\n runs: RichTextRun[];\n schema: TextSchema;\n font: Font;\n _cache: Map<string | number, unknown>;\n}): Promise<ResolvedRichTextRun[]> => {\n const { runs, schema, font, _cache } = arg;\n const fontKitCache = new Map<string, FontKitFont>();\n\n const getResolvedFontKitFont = async (fontName: string) => {\n const cached = fontKitCache.get(fontName);\n if (cached) return cached;\n\n const fontKitFont = await getFontKitFont(fontName, font, _cache as Map<string, FontKitFont>);\n fontKitCache.set(fontName, fontKitFont);\n return fontKitFont;\n };\n\n return Promise.all(\n runs.map(async (run) => {\n const resolution = resolveFontVariant(run, schema, font);\n return {\n ...run,\n ...resolution,\n fontKitFont: await getResolvedFontKitFont(resolution.fontName),\n };\n }),\n );\n};\n\nconst measureRunText = (\n run: ResolvedRichTextRun,\n text: string,\n fontSize: number,\n characterSpacing: number,\n) => {\n const syntheticBoldWidth = run.syntheticBold\n ? fontSize * SYNTHETIC_BOLD_OFFSET_RATIO * SYNTHETIC_BOLD_PDF_EXTRA_DRAWS\n : 0;\n const syntheticItalicWidth = run.syntheticItalic\n ? heightOfFontAtSize(run.fontKitFont, fontSize) *\n Math.tan((SYNTHETIC_ITALIC_SKEW_DEGREES * Math.PI) / 180)\n : 0;\n return (\n widthOfTextAtSize(text, run.fontKitFont, fontSize, characterSpacing) +\n syntheticBoldWidth +\n syntheticItalicWidth\n );\n};\n\nconst createLine = (): RichTextLine => ({ runs: [], width: 0, hardBreak: false });\n\nconst pushRunToLine = (\n line: RichTextLine,\n run: ResolvedRichTextRun,\n text: string,\n fontSize: number,\n characterSpacing: number,\n) => {\n if (!text) return;\n const width = measureRunText(run, text, fontSize, characterSpacing);\n if (line.runs.length > 0) line.width += characterSpacing;\n line.runs.push({ ...run, text, width });\n line.width += width;\n};\n\nconst measurePiecesWidth = (\n pieces: RichTextRunPiece[],\n fontSize: number,\n characterSpacing: number,\n) => {\n let width = 0;\n let hasText = false;\n pieces.forEach((piece) => {\n if (!piece.text) return;\n if (hasText) width += characterSpacing;\n width += measureRunText(piece.run, piece.text, fontSize, characterSpacing);\n hasText = true;\n });\n return width;\n};\n\nconst sliceRunPieces = (\n pieces: RichTextRunPiece[],\n startIndex: number,\n endIndex: number,\n): RichTextRunPiece[] => {\n const result: RichTextRunPiece[] = [];\n let offset = 0;\n\n pieces.forEach((piece) => {\n const pieceStart = offset;\n const pieceEnd = pieceStart + piece.text.length;\n const sliceStart = Math.max(startIndex, pieceStart);\n const sliceEnd = Math.min(endIndex, pieceEnd);\n\n if (sliceStart < sliceEnd) {\n result.push({\n run: piece.run,\n text: piece.text.slice(sliceStart - pieceStart, sliceEnd - pieceStart),\n });\n }\n\n offset = pieceEnd;\n });\n\n return result;\n};\n\nconst segmentRunPiecesByWord = (\n runs: ResolvedRichTextRun[],\n onSegment: (pieces: RichTextRunPiece[]) => void,\n onHardBreak: () => void,\n) => {\n let paragraphPieces: RichTextRunPiece[] = [];\n\n const flushParagraph = () => {\n if (paragraphPieces.length === 0) return;\n\n const paragraphText = paragraphPieces.map((piece) => piece.text).join('');\n Array.from(richTextWordSegmenter.segment(paragraphText), ({ segment, index }) => {\n const pieces = sliceRunPieces(paragraphPieces, index, index + segment.length);\n if (pieces.length > 0) onSegment(pieces);\n });\n paragraphPieces = [];\n };\n\n runs.forEach((run) => {\n run.text.split(/(\\r\\n|\\r|\\n)/).forEach((part) => {\n if (part === '\\r\\n' || part === '\\r' || part === '\\n') {\n flushParagraph();\n onHardBreak();\n return;\n }\n\n if (part) paragraphPieces.push({ run, text: part });\n });\n });\n\n flushParagraph();\n};\n\nconst splitIntoGraphemes = (value: string) =>\n Array.from(richTextGraphemeSegmenter.segment(value), ({ segment }) => segment);\n\nexport const countRichTextLineGraphemes = (line: RichTextLine) =>\n splitIntoGraphemes(line.runs.map((run) => run.text).join('')).length;\n\nexport const getRichTextLineText = (line: RichTextLine) =>\n line.runs.map((run) => run.text).join('');\n\nexport const layoutRichTextLines = (arg: {\n runs: ResolvedRichTextRun[];\n fontSize: number;\n characterSpacing: number;\n boxWidthInPt: number;\n}): RichTextLine[] => {\n const { runs, fontSize, characterSpacing, boxWidthInPt } = arg;\n const lines: RichTextLine[] = [];\n let currentLine = createLine();\n\n const pushCurrentLine = (hardBreak: boolean) => {\n currentLine.hardBreak = hardBreak;\n lines.push(currentLine);\n currentLine = createLine();\n };\n\n const pushPiecesToLine = (pieces: RichTextRunPiece[]) => {\n pieces.forEach((piece) => {\n pushRunToLine(currentLine, piece.run, piece.text, fontSize, characterSpacing);\n });\n };\n\n const pushOversizedText = (run: ResolvedRichTextRun, text: string) => {\n let remainingText = text;\n\n while (remainingText.length > 0) {\n const pendingSpacing = currentLine.runs.length > 0 ? characterSpacing : 0;\n const remainingWidth = Math.max(boxWidthInPt - currentLine.width - pendingSpacing, 0);\n const remainingTextWidth = measureRunText(run, remainingText, fontSize, characterSpacing);\n\n if (\n remainingTextWidth <= remainingWidth ||\n (currentLine.runs.length === 0 && remainingTextWidth <= boxWidthInPt)\n ) {\n pushRunToLine(currentLine, run, remainingText, fontSize, characterSpacing);\n return;\n }\n\n if (currentLine.runs.length > 0 && remainingTextWidth <= boxWidthInPt) {\n pushCurrentLine(false);\n continue;\n }\n\n const graphemes = splitIntoGraphemes(remainingText);\n let fittingText = '';\n let fittingLength = 0;\n\n for (const grapheme of graphemes) {\n const candidate = fittingText + grapheme;\n const candidateWidth = measureRunText(run, candidate, fontSize, characterSpacing);\n const maxWidth = currentLine.runs.length === 0 ? boxWidthInPt : remainingWidth;\n if (candidateWidth > maxWidth) {\n if (fittingText) break;\n if (currentLine.runs.length > 0) break;\n }\n fittingText = candidate;\n fittingLength += grapheme.length;\n if (candidateWidth > maxWidth) break;\n }\n\n if (!fittingText) {\n pushCurrentLine(false);\n continue;\n }\n\n pushRunToLine(currentLine, run, fittingText, fontSize, characterSpacing);\n remainingText = remainingText.slice(fittingLength);\n if (remainingText.length > 0) pushCurrentLine(false);\n }\n };\n\n const pushSegment = (pieces: RichTextRunPiece[]) => {\n const segmentWidth = measurePiecesWidth(pieces, fontSize, characterSpacing);\n const pendingSpacing = currentLine.runs.length > 0 ? characterSpacing : 0;\n const remainingWidth = Math.max(boxWidthInPt - currentLine.width - pendingSpacing, 0);\n\n if (\n segmentWidth <= remainingWidth ||\n (currentLine.runs.length === 0 && segmentWidth <= boxWidthInPt)\n ) {\n pushPiecesToLine(pieces);\n return;\n }\n\n if (currentLine.runs.length > 0) {\n pushCurrentLine(false);\n if (segmentWidth <= boxWidthInPt) {\n pushPiecesToLine(pieces);\n return;\n }\n }\n\n pieces.forEach((piece) => pushOversizedText(piece.run, piece.text));\n };\n\n segmentRunPiecesByWord(runs, pushSegment, () => pushCurrentLine(true));\n\n if (currentLine.runs.length > 0 || lines.length === 0) {\n pushCurrentLine(false);\n }\n\n return lines;\n};\n\nconst measureParagraphWidths = (\n runs: ResolvedRichTextRun[],\n fontSize: number,\n characterSpacing: number,\n) => {\n const widths: number[] = [];\n let paragraphPieces: RichTextRunPiece[] = [];\n\n const pushWidth = () => {\n widths.push(measurePiecesWidth(paragraphPieces, fontSize, characterSpacing));\n paragraphPieces = [];\n };\n\n runs.forEach((run) => {\n run.text.split(/(\\r\\n|\\r|\\n)/).forEach((part) => {\n if (part === '\\r\\n' || part === '\\r' || part === '\\n') {\n pushWidth();\n return;\n }\n\n if (part) paragraphPieces.push({ run, text: part });\n });\n });\n\n pushWidth();\n return widths;\n};\n\nconst getLineHeightAtSize = (line: RichTextLine, fontSize: number) => {\n if (line.runs.length === 0) return fontSize;\n return Math.max(...line.runs.map((run) => heightOfFontAtSize(run.fontKitFont, fontSize)));\n};\n\nexport const calculateDynamicRichTextFontSize = async (arg: {\n value: string;\n schema: TextSchema;\n font: Font;\n _cache: Map<string | number, unknown>;\n startingFontSize?: number | undefined;\n}) => {\n const { value, schema, font, _cache, startingFontSize } = arg;\n const {\n fontSize: schemaFontSize,\n dynamicFontSize: dynamicFontSizeSetting,\n characterSpacing: schemaCharacterSpacing,\n width: boxWidth,\n height: boxHeight,\n lineHeight = DEFAULT_LINE_HEIGHT,\n } = schema;\n const fontSize = startingFontSize || schemaFontSize || DEFAULT_FONT_SIZE;\n if (!dynamicFontSizeSetting) return fontSize;\n if (dynamicFontSizeSetting.max < dynamicFontSizeSetting.min) return fontSize;\n\n const richTextRuns = parseInlineMarkdown(value);\n const resolvedRuns = await resolveRichTextRuns({ runs: richTextRuns, schema, font, _cache });\n const characterSpacing = schemaCharacterSpacing ?? DEFAULT_CHARACTER_SPACING;\n const dynamicFontFit = dynamicFontSizeSetting.fit ?? DEFAULT_DYNAMIC_FIT;\n const boxWidthInPt = mm2pt(boxWidth);\n\n let dynamicFontSize = fontSize;\n if (dynamicFontSize < dynamicFontSizeSetting.min) {\n dynamicFontSize = dynamicFontSizeSetting.min;\n } else if (dynamicFontSize > dynamicFontSizeSetting.max) {\n dynamicFontSize = dynamicFontSizeSetting.max;\n }\n\n const calculateConstraints = (size: number) => {\n let totalWidthInMm = 0;\n let totalHeightInMm = 0;\n\n const lines = layoutRichTextLines({\n runs: resolvedRuns,\n fontSize: size,\n characterSpacing,\n boxWidthInPt,\n });\n\n lines.forEach((line, lineIndex) => {\n if (dynamicFontFit === DYNAMIC_FIT_VERTICAL) {\n totalWidthInMm = Math.max(totalWidthInMm, pt2mm(line.width));\n }\n\n if (lineIndex === 0) {\n totalHeightInMm += pt2mm(getLineHeightAtSize(line, size) * lineHeight);\n } else {\n totalHeightInMm += pt2mm(size * lineHeight);\n }\n });\n\n if (dynamicFontFit === DYNAMIC_FIT_HORIZONTAL) {\n measureParagraphWidths(resolvedRuns, size, characterSpacing).forEach((paragraphWidth) => {\n totalWidthInMm = Math.max(totalWidthInMm, pt2mm(paragraphWidth));\n });\n }\n\n return { totalWidthInMm, totalHeightInMm };\n };\n\n const shouldFontGrowToFit = (totalWidthInMm: number, totalHeightInMm: number) => {\n if (dynamicFontSize >= dynamicFontSizeSetting.max) {\n return false;\n }\n if (dynamicFontFit === DYNAMIC_FIT_HORIZONTAL) {\n return totalWidthInMm < boxWidth;\n }\n return totalHeightInMm < boxHeight;\n };\n\n const shouldFontShrinkToFit = (totalWidthInMm: number, totalHeightInMm: number) => {\n if (dynamicFontSize <= dynamicFontSizeSetting.min || dynamicFontSize <= 0) {\n return false;\n }\n return totalWidthInMm > boxWidth || totalHeightInMm > boxHeight;\n };\n\n let { totalWidthInMm, totalHeightInMm } = calculateConstraints(dynamicFontSize);\n\n while (shouldFontGrowToFit(totalWidthInMm, totalHeightInMm)) {\n dynamicFontSize += FONT_SIZE_ADJUSTMENT;\n const { totalWidthInMm: newWidth, totalHeightInMm: newHeight } =\n calculateConstraints(dynamicFontSize);\n\n if (newHeight < boxHeight) {\n totalWidthInMm = newWidth;\n totalHeightInMm = newHeight;\n } else {\n dynamicFontSize -= FONT_SIZE_ADJUSTMENT;\n break;\n }\n }\n\n while (shouldFontShrinkToFit(totalWidthInMm, totalHeightInMm)) {\n dynamicFontSize -= FONT_SIZE_ADJUSTMENT;\n ({ totalWidthInMm, totalHeightInMm } = calculateConstraints(dynamicFontSize));\n }\n\n return dynamicFontSize;\n};\n","import { getDefaultFont, mm2pt, pt2mm, type Font } from '@pdfme/common';\nimport type { Font as FontKitFont } from 'fontkit';\nimport { DEFAULT_CHARACTER_SPACING, DEFAULT_FONT_SIZE, DEFAULT_LINE_HEIGHT } from './constants.js';\nimport {\n calculateDynamicFontSize,\n getFontKitFont,\n heightOfFontAtSize,\n splitTextToSize,\n} from './helper.js';\nimport { parseInlineMarkdown } from './inlineMarkdown.js';\nimport {\n calculateDynamicRichTextFontSize,\n isInlineMarkdownTextSchema,\n layoutRichTextLines,\n resolveRichTextRuns,\n type RichTextLine,\n} from './richText.js';\nimport type { TextLineRange, TextSchema } from './types.js';\n\ntype MeasureTextHeightArgs = {\n value: string;\n schema: TextSchema;\n font?: Font;\n _cache?: Map<string | number, unknown>;\n ignoreDynamicFontSize?: boolean;\n};\n\ntype MeasureTextLinesResult = {\n lines: string[];\n lineHeights: number[];\n};\n\nexport const applyTextLineRange = <T>(lines: T[], range?: TextLineRange) => {\n if (!range) return lines;\n return lines.slice(range.start, range.end ?? lines.length);\n};\n\nexport const plainTextLinesToValue = (lines: string[]) =>\n lines.map((line) => line.replace(/[\\r\\n]+$/g, '')).join('\\n');\n\nconst splitReplacementTextToLines = (value: string) => {\n const lines: string[] = [];\n let start = 0;\n\n for (let i = 0; i < value.length; i += 1) {\n const charCode = value.charCodeAt(i);\n if (charCode !== 10 && charCode !== 13) continue;\n\n lines.push(value.slice(start, i));\n if (charCode === 13 && value.charCodeAt(i + 1) === 10) i += 1;\n start = i + 1;\n }\n\n lines.push(value.slice(start));\n return lines;\n};\n\nexport const measureTextLines = async ({\n value,\n schema,\n font = getDefaultFont(),\n _cache = new Map<string | number, unknown>(),\n ignoreDynamicFontSize = false,\n}: MeasureTextHeightArgs): Promise<MeasureTextLinesResult> => {\n const fontSize = schema.fontSize ?? DEFAULT_FONT_SIZE;\n const lineHeight = schema.lineHeight ?? DEFAULT_LINE_HEIGHT;\n const characterSpacing = schema.characterSpacing ?? DEFAULT_CHARACTER_SPACING;\n const boxWidthInPt = mm2pt(schema.width);\n\n if (isInlineMarkdownTextSchema(schema)) {\n const richTextRuns = parseInlineMarkdown(value);\n const resolvedRuns = await resolveRichTextRuns({ runs: richTextRuns, schema, font, _cache });\n const resolvedFontSize =\n schema.dynamicFontSize && schema.height > 0 && !ignoreDynamicFontSize\n ? await calculateDynamicRichTextFontSize({ value, schema, font, _cache })\n : fontSize;\n const lines = layoutRichTextLines({\n runs: resolvedRuns,\n fontSize: resolvedFontSize,\n characterSpacing,\n boxWidthInPt,\n });\n\n return {\n lines: lines.map((line) => line.runs.map((run) => run.text).join('')),\n lineHeights: measureRichTextLineHeights(lines, resolvedFontSize, lineHeight),\n };\n }\n\n const fontKitFont = await getFontKitFont(\n schema.fontName,\n font,\n _cache as Map<string, FontKitFont>,\n );\n const resolvedFontSize =\n schema.dynamicFontSize && schema.height > 0 && !ignoreDynamicFontSize\n ? calculateDynamicFontSize({ textSchema: schema, fontKitFont, value })\n : fontSize;\n const lines = splitTextToSize({\n value,\n characterSpacing,\n fontSize: resolvedFontSize,\n fontKitFont,\n boxWidthInPt,\n });\n\n return {\n lines,\n lineHeights: measurePlainTextLineHeights(lines, fontKitFont, resolvedFontSize, lineHeight),\n };\n};\n\nexport const mergeTextLineRangeValue = async ({\n value,\n replacement,\n schema,\n font = getDefaultFont(),\n _cache = new Map<string | number, unknown>(),\n}: {\n value: string;\n replacement: string;\n schema: TextSchema;\n font?: Font;\n _cache?: Map<string | number, unknown>;\n}) => {\n if (!schema.__textLineRange) return replacement;\n\n const { lines } = await measureTextLines({\n value,\n schema,\n font,\n _cache,\n ignoreDynamicFontSize: true,\n });\n const { start, end = lines.length } = schema.__textLineRange;\n const nextLines = [...lines];\n nextLines.splice(start, end - start, ...splitReplacementTextToLines(replacement));\n return plainTextLinesToValue(nextLines);\n};\n\nexport const measureTextHeight = async (args: MeasureTextHeightArgs): Promise<number> => {\n const { lineHeights } = await measureTextLines(args);\n return sumLineHeights(lineHeights);\n};\n\nexport const sumLineHeights = (lineHeights: number[]) =>\n lineHeights.reduce((sum, height) => sum + height, 0);\n\nconst measurePlainTextLineHeights = (\n lines: string[],\n fontKitFont: FontKitFont,\n fontSize: number,\n lineHeight: number,\n) => {\n if (lines.length === 0) return [];\n const firstLineHeight = heightOfFontAtSize(fontKitFont, fontSize) * lineHeight;\n const otherLineHeight = fontSize * lineHeight;\n return lines.map((_, index) => pt2mm(index === 0 ? firstLineHeight : otherLineHeight));\n};\n\nconst measureRichTextLineHeights = (\n lines: RichTextLine[],\n fontSize: number,\n lineHeight: number,\n) => {\n if (lines.length === 0) return [];\n return lines.map((line, index) =>\n pt2mm((index === 0 ? getRichTextLineHeight(line, fontSize) : fontSize) * lineHeight),\n );\n};\n\nconst getRichTextLineHeight = (line: RichTextLine, fontSize: number) => {\n if (line.runs.length === 0) return fontSize;\n return Math.max(...line.runs.map((run) => heightOfFontAtSize(run.fontKitFont, fontSize)));\n};\n"],"mappings":"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"}