@pdfme/schemas 6.1.0 → 6.1.1-dev.11

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 (62) hide show
  1. package/dist/{builtins-C0BvXHWr.js → builtins-Clh58o_b.js} +313 -483
  2. package/dist/builtins-Clh58o_b.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 +4 -0
  7. package/dist/dynamicLayout.js +20 -0
  8. package/dist/dynamicLayout.js.map +1 -0
  9. package/dist/dynamicTemplate-CB2Hj9cN.js +65 -0
  10. package/dist/dynamicTemplate-CB2Hj9cN.js.map +1 -0
  11. package/dist/{dynamicTemplate-Dsrw11aL.js → dynamicTemplate-CjbGepw4.js} +24 -358
  12. package/dist/dynamicTemplate-CjbGepw4.js.map +1 -0
  13. package/dist/dynamicTemplate-Fn7mpUsu.js +114 -0
  14. package/dist/dynamicTemplate-Fn7mpUsu.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-BJzBqIT4.js +40 -0
  18. package/dist/helper-BJzBqIT4.js.map +1 -0
  19. package/dist/index.d.ts +5 -2
  20. package/dist/index.js +847 -205
  21. package/dist/index.js.map +1 -1
  22. package/dist/list/constants.d.ts +10 -0
  23. package/dist/list/dynamicTemplate.d.ts +2 -0
  24. package/dist/list/helper.d.ts +15 -0
  25. package/dist/list/index.d.ts +4 -0
  26. package/dist/list/pdfRender.d.ts +3 -0
  27. package/dist/list/propPanel.d.ts +3 -0
  28. package/dist/list/types.d.ts +31 -0
  29. package/dist/list/uiRender.d.ts +3 -0
  30. package/dist/lists.d.ts +4 -0
  31. package/dist/lists.js +3 -0
  32. package/dist/measure-Bjmh9Ro3.js +585 -0
  33. package/dist/measure-Bjmh9Ro3.js.map +1 -0
  34. package/dist/multiVariableText/dynamicTemplate.d.ts +2 -0
  35. package/dist/radioGroup/index.d.ts +2 -2
  36. package/dist/select/index.d.ts +2 -2
  37. package/dist/shapes/line.d.ts +1 -1
  38. package/dist/shapes/rectAndEllipse.d.ts +1 -2
  39. package/dist/splitRange-CpXivbmJ.js +398 -0
  40. package/dist/splitRange-CpXivbmJ.js.map +1 -0
  41. package/dist/splitRange.d.ts +16 -0
  42. package/dist/tables/dynamicTemplate.d.ts +2 -1
  43. package/dist/tables/helper.d.ts +8 -8
  44. package/dist/tables.d.ts +2 -1
  45. package/dist/tables.js +3 -2
  46. package/dist/text/constants.d.ts +3 -0
  47. package/dist/text/dynamicTemplate.d.ts +2 -0
  48. package/dist/text/linkAnnotation.d.ts +14 -0
  49. package/dist/text/measure.d.ts +26 -0
  50. package/dist/text/overflow.d.ts +7 -0
  51. package/dist/text/richTextPdfRender.d.ts +2 -1
  52. package/dist/text/types.d.ts +3 -0
  53. package/dist/texts.d.ts +5 -0
  54. package/dist/texts.js +4 -0
  55. package/dist/types.d.ts +15 -0
  56. package/dist/types.js +0 -0
  57. package/dist/utils.d.ts +1 -0
  58. package/dist/utils.js +3 -2
  59. package/dist/utils.js.map +1 -1
  60. package/package.json +21 -1
  61. package/dist/builtins-C0BvXHWr.js.map +0 -1
  62. package/dist/dynamicTemplate-Dsrw11aL.js.map +0 -1
@@ -0,0 +1,10 @@
1
+ import type { LIST_STYLE } from './types.js';
2
+ export declare const LIST_STYLE_BULLET: LIST_STYLE;
3
+ export declare const LIST_STYLE_ORDERED: LIST_STYLE;
4
+ export declare const DEFAULT_LIST_STYLE: LIST_STYLE;
5
+ export declare const DEFAULT_MARKER = "\u2022";
6
+ export declare const DEFAULT_MARKER_WIDTH = 6;
7
+ export declare const DEFAULT_MARKER_GAP = 2;
8
+ export declare const DEFAULT_INDENT_SIZE = 6;
9
+ export declare const DEFAULT_ITEM_SPACING = 1;
10
+ export declare const MAX_INDENT_LEVEL = 8;
@@ -0,0 +1,2 @@
1
+ import type { DynamicLayoutArgs, DynamicLayoutResult } from '@pdfme/common';
2
+ export declare const getDynamicLayoutForList: (value: string, args: DynamicLayoutArgs) => Promise<DynamicLayoutResult>;
@@ -0,0 +1,15 @@
1
+ import { CommonOptions } from '@pdfme/common';
2
+ import type { ListItem, ListLayout, ListSchema } from './types.js';
3
+ export declare const normalizeListItems: (value: unknown) => string[];
4
+ export declare const parseListItem: (value: string) => ListItem;
5
+ export declare const normalizeListItemEntries: (value: unknown) => ListItem[];
6
+ export declare const serializeListItems: (items: ListItem[]) => string;
7
+ export declare const getListMarkers: (schema: ListSchema, items: string[]) => string[];
8
+ export declare const calculateListLayout: (arg: {
9
+ schema: ListSchema;
10
+ items: string[];
11
+ markerItems?: string[];
12
+ startIndex: number;
13
+ options: CommonOptions;
14
+ _cache: Map<string | number, unknown>;
15
+ }) => Promise<ListLayout>;
@@ -0,0 +1,4 @@
1
+ import type { Plugin } from '@pdfme/common';
2
+ import type { ListSchema } from './types.js';
3
+ declare const listSchema: Plugin<ListSchema>;
4
+ export default listSchema;
@@ -0,0 +1,3 @@
1
+ import type { PDFRenderProps } from '@pdfme/common';
2
+ import type { ListSchema } from './types.js';
3
+ export declare const pdfRender: (arg: PDFRenderProps<ListSchema>) => Promise<void>;
@@ -0,0 +1,3 @@
1
+ import type { PropPanel } from '@pdfme/common';
2
+ import type { ListSchema } from './types.js';
3
+ export declare const propPanel: PropPanel<ListSchema>;
@@ -0,0 +1,31 @@
1
+ import type { TextSchema } from '../text/types.js';
2
+ export type LIST_STYLE = 'bullet' | 'ordered';
3
+ export type ListSchema = TextSchema & {
4
+ listStyle: LIST_STYLE;
5
+ markerWidth: number;
6
+ markerGap: number;
7
+ indentSize?: number;
8
+ itemSpacing: number;
9
+ };
10
+ export type ListItem = {
11
+ text: string;
12
+ level: number;
13
+ };
14
+ export type ListItemLayout = {
15
+ item: string;
16
+ itemIndex: number;
17
+ level: number;
18
+ marker: string;
19
+ lines: string[];
20
+ height: number;
21
+ markerX: number;
22
+ bodyX: number;
23
+ bodyWidth: number;
24
+ };
25
+ export type ListLayout = {
26
+ items: ListItemLayout[];
27
+ totalHeight: number;
28
+ markerWidth: number;
29
+ markerGap: number;
30
+ indentSize: number;
31
+ };
@@ -0,0 +1,3 @@
1
+ import { UIRenderProps } from '@pdfme/common';
2
+ import type { ListSchema } from './types.js';
3
+ export declare const uiRender: (arg: UIRenderProps<ListSchema>) => Promise<void>;
@@ -0,0 +1,4 @@
1
+ export { getDynamicLayoutForList } from './list/dynamicTemplate.js';
2
+ export { createListItemSplitRange, getListItemRange, LIST_ITEM_SPLIT_UNIT } from './splitRange.js';
3
+ export { normalizeListItems, normalizeListItemEntries, serializeListItems, getListMarkers, calculateListLayout, } from './list/helper.js';
4
+ export type { ListItem, ListSchema, ListLayout, ListItemLayout, LIST_STYLE } from './list/types.js';
package/dist/lists.js ADDED
@@ -0,0 +1,3 @@
1
+ import { a as createListItemSplitRange, c as getListItemRange, n as LIST_ITEM_SPLIT_UNIT } from "./splitRange-CpXivbmJ.js";
2
+ import { a as normalizeListItems, i as normalizeListItemEntries, n as calculateListLayout, o as serializeListItems, r as getListMarkers, t as getDynamicLayoutForList } from "./dynamicTemplate-Fn7mpUsu.js";
3
+ export { LIST_ITEM_SPLIT_UNIT, calculateListLayout, createListItemSplitRange, getDynamicLayoutForList, getListItemRange, getListMarkers, normalizeListItemEntries, normalizeListItems, serializeListItems };
@@ -0,0 +1,585 @@
1
+ import { B as SYNTHETIC_BOLD_OFFSET_RATIO, P as FONT_SIZE_ADJUSTMENT, d as calculateDynamicFontSize, g as heightOfFontAtSize, h as getFontKitFont, u as getTextLineRange, v as splitTextToSize, y as widthOfTextAtSize } from "./splitRange-CpXivbmJ.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
+ const range = getTextLineRange(schema);
550
+ if (!range) return replacement;
551
+ const { lines } = await measureTextLines({
552
+ value,
553
+ schema,
554
+ font,
555
+ _cache,
556
+ ignoreDynamicFontSize: true
557
+ });
558
+ const { start, end = lines.length } = range;
559
+ const nextLines = [...lines];
560
+ nextLines.splice(start, end - start, ...splitReplacementTextToLines(replacement));
561
+ return plainTextLinesToValue(nextLines);
562
+ };
563
+ var measureTextHeight = async (args) => {
564
+ const { lineHeights } = await measureTextLines(args);
565
+ return sumLineHeights(lineHeights);
566
+ };
567
+ var sumLineHeights = (lineHeights) => lineHeights.reduce((sum, height) => sum + height, 0);
568
+ var measurePlainTextLineHeights = (lines, fontKitFont, fontSize, lineHeight) => {
569
+ if (lines.length === 0) return [];
570
+ const firstLineHeight = heightOfFontAtSize(fontKitFont, fontSize) * lineHeight;
571
+ const otherLineHeight = fontSize * lineHeight;
572
+ return lines.map((_, index) => pt2mm(index === 0 ? firstLineHeight : otherLineHeight));
573
+ };
574
+ var measureRichTextLineHeights = (lines, fontSize, lineHeight) => {
575
+ if (lines.length === 0) return [];
576
+ return lines.map((line, index) => pt2mm((index === 0 ? getRichTextLineHeight(line, fontSize) : fontSize) * lineHeight));
577
+ };
578
+ var getRichTextLineHeight = (line, fontSize) => {
579
+ if (line.runs.length === 0) return fontSize;
580
+ return Math.max(...line.runs.map((run) => heightOfFontAtSize(run.fontKitFont, fontSize)));
581
+ };
582
+ //#endregion
583
+ 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 };
584
+
585
+ //# sourceMappingURL=measure-Bjmh9Ro3.js.map