@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.
- package/dist/{builtins-C0BvXHWr.js → builtins-Clh58o_b.js} +313 -483
- package/dist/builtins-Clh58o_b.js.map +1 -0
- package/dist/builtins.d.ts +1 -1
- package/dist/builtins.js +1 -1
- package/dist/checkbox/index.d.ts +2 -2
- package/dist/dynamicLayout.d.ts +4 -0
- package/dist/dynamicLayout.js +20 -0
- package/dist/dynamicLayout.js.map +1 -0
- package/dist/dynamicTemplate-CB2Hj9cN.js +65 -0
- package/dist/dynamicTemplate-CB2Hj9cN.js.map +1 -0
- package/dist/{dynamicTemplate-Dsrw11aL.js → dynamicTemplate-CjbGepw4.js} +24 -358
- package/dist/dynamicTemplate-CjbGepw4.js.map +1 -0
- package/dist/dynamicTemplate-Fn7mpUsu.js +114 -0
- package/dist/dynamicTemplate-Fn7mpUsu.js.map +1 -0
- package/dist/graphics/image.d.ts +1 -1
- package/dist/graphics/signature.d.ts +1 -1
- package/dist/helper-BJzBqIT4.js +40 -0
- package/dist/helper-BJzBqIT4.js.map +1 -0
- package/dist/index.d.ts +5 -2
- package/dist/index.js +847 -205
- package/dist/index.js.map +1 -1
- package/dist/list/constants.d.ts +10 -0
- package/dist/list/dynamicTemplate.d.ts +2 -0
- package/dist/list/helper.d.ts +15 -0
- package/dist/list/index.d.ts +4 -0
- package/dist/list/pdfRender.d.ts +3 -0
- package/dist/list/propPanel.d.ts +3 -0
- package/dist/list/types.d.ts +31 -0
- package/dist/list/uiRender.d.ts +3 -0
- package/dist/lists.d.ts +4 -0
- package/dist/lists.js +3 -0
- package/dist/measure-Bjmh9Ro3.js +585 -0
- package/dist/measure-Bjmh9Ro3.js.map +1 -0
- package/dist/multiVariableText/dynamicTemplate.d.ts +2 -0
- package/dist/radioGroup/index.d.ts +2 -2
- package/dist/select/index.d.ts +2 -2
- package/dist/shapes/line.d.ts +1 -1
- package/dist/shapes/rectAndEllipse.d.ts +1 -2
- package/dist/splitRange-CpXivbmJ.js +398 -0
- package/dist/splitRange-CpXivbmJ.js.map +1 -0
- package/dist/splitRange.d.ts +16 -0
- package/dist/tables/dynamicTemplate.d.ts +2 -1
- package/dist/tables/helper.d.ts +8 -8
- package/dist/tables.d.ts +2 -1
- package/dist/tables.js +3 -2
- package/dist/text/constants.d.ts +3 -0
- package/dist/text/dynamicTemplate.d.ts +2 -0
- package/dist/text/linkAnnotation.d.ts +14 -0
- package/dist/text/measure.d.ts +26 -0
- package/dist/text/overflow.d.ts +7 -0
- package/dist/text/richTextPdfRender.d.ts +2 -1
- package/dist/text/types.d.ts +3 -0
- package/dist/texts.d.ts +5 -0
- package/dist/texts.js +4 -0
- package/dist/types.d.ts +15 -0
- package/dist/types.js +0 -0
- package/dist/utils.d.ts +1 -0
- package/dist/utils.js +3 -2
- package/dist/utils.js.map +1 -1
- package/package.json +21 -1
- package/dist/builtins-C0BvXHWr.js.map +0 -1
- 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,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,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
|
+
};
|
package/dist/lists.d.ts
ADDED
|
@@ -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
|