@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
|
@@ -1,436 +1,52 @@
|
|
|
1
|
-
import { A as
|
|
1
|
+
import { A as DEFAULT_TEXT_FORMAT, B as SYNTHETIC_BOLD_OFFSET_RATIO, C as ALIGN_RIGHT, D as DEFAULT_DYNAMIC_FIT, E as DEFAULT_ALIGNMENT, F as FONT_VARIANT_FALLBACK_ERROR, G as VERTICAL_ALIGN_BOTTOM, H as TEXT_FORMAT_PLAIN, I as FONT_VARIANT_FALLBACK_PLAIN, K as VERTICAL_ALIGN_MIDDLE, L as FONT_VARIANT_FALLBACK_SYNTHETIC, M as DYNAMIC_FIT_HORIZONTAL, N as DYNAMIC_FIT_VERTICAL, O as DEFAULT_FONT_COLOR, R as PLACEHOLDER_FONT_COLOR, T as CODE_HORIZONTAL_PADDING, U as TEXT_OVERFLOW_EXPAND, V as TEXT_FORMAT_INLINE_MARKDOWN, W as TEXT_OVERFLOW_VISIBLE, _ as isFirefox, b as ALIGN_CENTER, d as calculateDynamicFontSize, f as fetchRemoteFontData, g as heightOfFontAtSize, h as getFontKitFont, j as DEFAULT_TEXT_OVERFLOW, k as DEFAULT_FONT_VARIANT_FALLBACK, m as getFontDescentInPt, p as getBrowserVerticalFontAdjustments, u as getTextLineRange, v as splitTextToSize, w as CODE_BACKGROUND_COLOR, x as ALIGN_JUSTIFY, y as widthOfTextAtSize, z as SYNTHETIC_BOLD_CSS_TEXT_SHADOW } from "./splitRange-CpXivbmJ.js";
|
|
2
|
+
import { a as plainTextLinesToValue, c as countRichTextLineGraphemes, f as resolveRichTextRuns, h as stripInlineMarkdown, l as isInlineMarkdownTextSchema, m as parseInlineMarkdown, s as calculateDynamicRichTextFontSize, t as applyTextLineRange, u as layoutRichTextLines } from "./measure-Bjmh9Ro3.js";
|
|
3
|
+
import { c as HEX_COLOR_PATTERN } from "./dynamicTemplate-CjbGepw4.js";
|
|
2
4
|
import { convertForPdfLayoutProps, createSvgStr, hex2PrintingColor, isEditable, rotatePoint } from "./utils.js";
|
|
3
|
-
import { DEFAULT_FONT_NAME, getDefaultFont, getFallbackFontName, mm2pt,
|
|
5
|
+
import { DEFAULT_FONT_NAME, getDefaultFont, getFallbackFontName, getInternalLinkTarget, isBlankPdf, mm2pt, normalizeLinkHref, normalizeSafeLinkUri, registerInternalLinkAnnotation } from "@pdfme/common";
|
|
6
|
+
import { PDFName, PDFString } from "@pdfme/pdf-lib";
|
|
4
7
|
import { AlignCenter, AlignJustify, AlignLeft, AlignRight, ArrowDownToLine, ArrowUpToLine, Strikethrough, TextCursorInput, Underline } from "lucide";
|
|
5
|
-
//#region src/text/
|
|
6
|
-
var
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
});
|
|
29
|
-
};
|
|
30
|
-
var findClosingDelimiter = (value, delimiter, from) => {
|
|
31
|
-
for (let i = from; i < value.length; i++) {
|
|
32
|
-
if (value[i] === "\\") {
|
|
33
|
-
i += 1;
|
|
34
|
-
continue;
|
|
35
|
-
}
|
|
36
|
-
if (delimiter !== "`" && value[i] === "`") {
|
|
37
|
-
const codeEnd = findClosingDelimiter(value, "`", i + 1);
|
|
38
|
-
if (codeEnd === -1) continue;
|
|
39
|
-
i = codeEnd;
|
|
40
|
-
continue;
|
|
41
|
-
}
|
|
42
|
-
if (value.startsWith(delimiter, i)) return i;
|
|
43
|
-
}
|
|
44
|
-
return -1;
|
|
45
|
-
};
|
|
46
|
-
var getDelimiter = (value, index) => {
|
|
47
|
-
if (value[index] === "`") return "`";
|
|
48
|
-
if (value.startsWith("***", index)) return "***";
|
|
49
|
-
if (value.startsWith("**", index)) return "**";
|
|
50
|
-
if (value.startsWith("~~", index)) return "~~";
|
|
51
|
-
if (value[index] === "*") return "*";
|
|
52
|
-
return "";
|
|
53
|
-
};
|
|
54
|
-
var mergeStyle = (style, delimiter) => {
|
|
55
|
-
if (delimiter === "***") return {
|
|
56
|
-
...style,
|
|
57
|
-
bold: true,
|
|
58
|
-
italic: true
|
|
59
|
-
};
|
|
60
|
-
if (delimiter === "**") return {
|
|
61
|
-
...style,
|
|
62
|
-
bold: true
|
|
63
|
-
};
|
|
64
|
-
if (delimiter === "*") return {
|
|
65
|
-
...style,
|
|
66
|
-
italic: true
|
|
67
|
-
};
|
|
68
|
-
if (delimiter === "~~") return {
|
|
69
|
-
...style,
|
|
70
|
-
strikethrough: true
|
|
71
|
-
};
|
|
72
|
-
return style;
|
|
73
|
-
};
|
|
74
|
-
var parseRange = (value, from, to, style) => {
|
|
75
|
-
const runs = [];
|
|
76
|
-
let buffer = "";
|
|
77
|
-
const flush = () => {
|
|
78
|
-
appendRun(runs, buffer, style);
|
|
79
|
-
buffer = "";
|
|
80
|
-
};
|
|
81
|
-
for (let index = from; index < to; index++) {
|
|
82
|
-
const char = value[index];
|
|
83
|
-
if (char === "\\" && index + 1 < to && MARKDOWN_ESCAPABLE_CHARS.has(value[index + 1])) {
|
|
84
|
-
buffer += value[index + 1];
|
|
85
|
-
index += 1;
|
|
86
|
-
continue;
|
|
87
|
-
}
|
|
88
|
-
const delimiter = getDelimiter(value, index);
|
|
89
|
-
if (!delimiter) {
|
|
90
|
-
buffer += char;
|
|
91
|
-
continue;
|
|
92
|
-
}
|
|
93
|
-
const closingIndex = findClosingDelimiter(value, delimiter, index + delimiter.length);
|
|
94
|
-
if (closingIndex === -1 || closingIndex + delimiter.length > to) {
|
|
95
|
-
buffer += char;
|
|
96
|
-
continue;
|
|
97
|
-
}
|
|
98
|
-
flush();
|
|
99
|
-
if (delimiter === "`") appendRun(runs, value.slice(index + 1, closingIndex).replace(MARKDOWN_UNESCAPE_PATTERN, "$1"), {
|
|
100
|
-
...style,
|
|
101
|
-
code: true
|
|
102
|
-
});
|
|
103
|
-
else parseRange(value, index + delimiter.length, closingIndex, mergeStyle(style, delimiter)).forEach((run) => appendRun(runs, run.text, run));
|
|
104
|
-
index = closingIndex + delimiter.length - 1;
|
|
105
|
-
}
|
|
106
|
-
flush();
|
|
107
|
-
return runs;
|
|
108
|
-
};
|
|
109
|
-
var parseInlineMarkdown = (value) => {
|
|
110
|
-
if (!value) return [];
|
|
111
|
-
return parseRange(value, 0, value.length, {});
|
|
112
|
-
};
|
|
113
|
-
var escapeInlineMarkdown = (value) => value.replace(MARKDOWN_ESCAPE_PATTERN, (char) => `\\${char}`);
|
|
114
|
-
var stripInlineMarkdown = (value) => parseInlineMarkdown(value).map((run) => run.text).join("");
|
|
115
|
-
//#endregion
|
|
116
|
-
//#region src/text/richText.ts
|
|
117
|
-
var richTextWordSegmenter = new Intl.Segmenter(void 0, { granularity: "word" });
|
|
118
|
-
var richTextGraphemeSegmenter = new Intl.Segmenter(void 0, { granularity: "grapheme" });
|
|
119
|
-
var getBaseFontName = (schema, font) => schema.fontName && font[schema.fontName] ? schema.fontName : getFallbackFontName(font);
|
|
120
|
-
var getLoadedFontName = (font, fontName) => fontName && font[fontName] ? fontName : void 0;
|
|
121
|
-
var isInlineMarkdownTextSchema = (schema) => schema.textFormat === "inline-markdown" && !(schema.type === "text" && schema.readOnly !== true);
|
|
122
|
-
var resolveFontVariant = (run, schema, font) => {
|
|
123
|
-
const baseFontName = getBaseFontName(schema, font);
|
|
124
|
-
const variants = schema.fontVariants ?? {};
|
|
125
|
-
const fallback = schema.fontVariantFallback ?? "synthetic";
|
|
126
|
-
let fontName = baseFontName;
|
|
127
|
-
let needsBold = Boolean(run.bold);
|
|
128
|
-
let needsItalic = Boolean(run.italic);
|
|
129
|
-
if (run.code) fontName = getLoadedFontName(font, variants.code) ?? baseFontName;
|
|
130
|
-
else if (run.bold && run.italic) {
|
|
131
|
-
const boldItalic = getLoadedFontName(font, variants.boldItalic);
|
|
132
|
-
const italic = getLoadedFontName(font, variants.italic);
|
|
133
|
-
const bold = getLoadedFontName(font, variants.bold);
|
|
134
|
-
if (boldItalic) {
|
|
135
|
-
fontName = boldItalic;
|
|
136
|
-
needsBold = false;
|
|
137
|
-
needsItalic = false;
|
|
138
|
-
} else if (italic) {
|
|
139
|
-
fontName = italic;
|
|
140
|
-
needsItalic = false;
|
|
141
|
-
} else if (bold) {
|
|
142
|
-
fontName = bold;
|
|
143
|
-
needsBold = false;
|
|
144
|
-
}
|
|
145
|
-
} else if (run.bold) {
|
|
146
|
-
const bold = getLoadedFontName(font, variants.bold);
|
|
147
|
-
if (bold) {
|
|
148
|
-
fontName = bold;
|
|
149
|
-
needsBold = false;
|
|
150
|
-
}
|
|
151
|
-
} else if (run.italic) {
|
|
152
|
-
const italic = getLoadedFontName(font, variants.italic);
|
|
153
|
-
if (italic) {
|
|
154
|
-
fontName = italic;
|
|
155
|
-
needsItalic = false;
|
|
8
|
+
//#region src/text/linkAnnotation.ts
|
|
9
|
+
var addUriLinkAnnotation = (arg) => {
|
|
10
|
+
const { pdfDoc, page, uri, rect, borderWidth = 0 } = arg;
|
|
11
|
+
const safeUri = normalizeSafeLinkUri(uri);
|
|
12
|
+
if (!safeUri || rect.width <= 0 || rect.height <= 0) return;
|
|
13
|
+
const annotationRef = pdfDoc.context.register(pdfDoc.context.obj({
|
|
14
|
+
Type: PDFName.of("Annot"),
|
|
15
|
+
Subtype: PDFName.of("Link"),
|
|
16
|
+
Rect: [
|
|
17
|
+
rect.x,
|
|
18
|
+
rect.y,
|
|
19
|
+
rect.x + rect.width,
|
|
20
|
+
rect.y + rect.height
|
|
21
|
+
],
|
|
22
|
+
Border: [
|
|
23
|
+
0,
|
|
24
|
+
0,
|
|
25
|
+
borderWidth
|
|
26
|
+
],
|
|
27
|
+
A: {
|
|
28
|
+
Type: PDFName.of("Action"),
|
|
29
|
+
S: PDFName.of("URI"),
|
|
30
|
+
URI: PDFString.of(safeUri)
|
|
156
31
|
}
|
|
157
|
-
}
|
|
158
|
-
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}".`);
|
|
159
|
-
return {
|
|
160
|
-
fontName,
|
|
161
|
-
syntheticBold: fallback !== "plain" && needsBold,
|
|
162
|
-
syntheticItalic: fallback !== "plain" && needsItalic
|
|
163
|
-
};
|
|
164
|
-
};
|
|
165
|
-
var resolveRichTextRuns = async (arg) => {
|
|
166
|
-
const { runs, schema, font, _cache } = arg;
|
|
167
|
-
const fontKitCache = /* @__PURE__ */ new Map();
|
|
168
|
-
const getResolvedFontKitFont = async (fontName) => {
|
|
169
|
-
const cached = fontKitCache.get(fontName);
|
|
170
|
-
if (cached) return cached;
|
|
171
|
-
const fontKitFont = await getFontKitFont(fontName, font, _cache);
|
|
172
|
-
fontKitCache.set(fontName, fontKitFont);
|
|
173
|
-
return fontKitFont;
|
|
174
|
-
};
|
|
175
|
-
return Promise.all(runs.map(async (run) => {
|
|
176
|
-
const resolution = resolveFontVariant(run, schema, font);
|
|
177
|
-
return {
|
|
178
|
-
...run,
|
|
179
|
-
...resolution,
|
|
180
|
-
fontKitFont: await getResolvedFontKitFont(resolution.fontName)
|
|
181
|
-
};
|
|
182
32
|
}));
|
|
183
|
-
|
|
184
|
-
var measureRunText = (run, text, fontSize, characterSpacing) => {
|
|
185
|
-
const syntheticBoldWidth = run.syntheticBold ? fontSize * SYNTHETIC_BOLD_OFFSET_RATIO * 2 : 0;
|
|
186
|
-
const syntheticItalicWidth = run.syntheticItalic ? heightOfFontAtSize(run.fontKitFont, fontSize) * Math.tan(12 * Math.PI / 180) : 0;
|
|
187
|
-
return widthOfTextAtSize(text, run.fontKitFont, fontSize, characterSpacing) + syntheticBoldWidth + syntheticItalicWidth;
|
|
188
|
-
};
|
|
189
|
-
var createLine = () => ({
|
|
190
|
-
runs: [],
|
|
191
|
-
width: 0,
|
|
192
|
-
hardBreak: false
|
|
193
|
-
});
|
|
194
|
-
var pushRunToLine = (line, run, text, fontSize, characterSpacing) => {
|
|
195
|
-
if (!text) return;
|
|
196
|
-
const width = measureRunText(run, text, fontSize, characterSpacing);
|
|
197
|
-
if (line.runs.length > 0) line.width += characterSpacing;
|
|
198
|
-
line.runs.push({
|
|
199
|
-
...run,
|
|
200
|
-
text,
|
|
201
|
-
width
|
|
202
|
-
});
|
|
203
|
-
line.width += width;
|
|
204
|
-
};
|
|
205
|
-
var measurePiecesWidth = (pieces, fontSize, characterSpacing) => {
|
|
206
|
-
let width = 0;
|
|
207
|
-
let hasText = false;
|
|
208
|
-
pieces.forEach((piece) => {
|
|
209
|
-
if (!piece.text) return;
|
|
210
|
-
if (hasText) width += characterSpacing;
|
|
211
|
-
width += measureRunText(piece.run, piece.text, fontSize, characterSpacing);
|
|
212
|
-
hasText = true;
|
|
213
|
-
});
|
|
214
|
-
return width;
|
|
215
|
-
};
|
|
216
|
-
var sliceRunPieces = (pieces, startIndex, endIndex) => {
|
|
217
|
-
const result = [];
|
|
218
|
-
let offset = 0;
|
|
219
|
-
pieces.forEach((piece) => {
|
|
220
|
-
const pieceStart = offset;
|
|
221
|
-
const pieceEnd = pieceStart + piece.text.length;
|
|
222
|
-
const sliceStart = Math.max(startIndex, pieceStart);
|
|
223
|
-
const sliceEnd = Math.min(endIndex, pieceEnd);
|
|
224
|
-
if (sliceStart < sliceEnd) result.push({
|
|
225
|
-
run: piece.run,
|
|
226
|
-
text: piece.text.slice(sliceStart - pieceStart, sliceEnd - pieceStart)
|
|
227
|
-
});
|
|
228
|
-
offset = pieceEnd;
|
|
229
|
-
});
|
|
230
|
-
return result;
|
|
231
|
-
};
|
|
232
|
-
var segmentRunPiecesByWord = (runs, onSegment, onHardBreak) => {
|
|
233
|
-
let paragraphPieces = [];
|
|
234
|
-
const flushParagraph = () => {
|
|
235
|
-
if (paragraphPieces.length === 0) return;
|
|
236
|
-
const paragraphText = paragraphPieces.map((piece) => piece.text).join("");
|
|
237
|
-
Array.from(richTextWordSegmenter.segment(paragraphText), ({ segment, index }) => {
|
|
238
|
-
const pieces = sliceRunPieces(paragraphPieces, index, index + segment.length);
|
|
239
|
-
if (pieces.length > 0) onSegment(pieces);
|
|
240
|
-
});
|
|
241
|
-
paragraphPieces = [];
|
|
242
|
-
};
|
|
243
|
-
runs.forEach((run) => {
|
|
244
|
-
run.text.split(/(\r\n|\r|\n)/).forEach((part) => {
|
|
245
|
-
if (part === "\r\n" || part === "\r" || part === "\n") {
|
|
246
|
-
flushParagraph();
|
|
247
|
-
onHardBreak();
|
|
248
|
-
return;
|
|
249
|
-
}
|
|
250
|
-
if (part) paragraphPieces.push({
|
|
251
|
-
run,
|
|
252
|
-
text: part
|
|
253
|
-
});
|
|
254
|
-
});
|
|
255
|
-
});
|
|
256
|
-
flushParagraph();
|
|
257
|
-
};
|
|
258
|
-
var splitIntoGraphemes = (value) => Array.from(richTextGraphemeSegmenter.segment(value), ({ segment }) => segment);
|
|
259
|
-
var countRichTextLineGraphemes = (line) => splitIntoGraphemes(line.runs.map((run) => run.text).join("")).length;
|
|
260
|
-
var layoutRichTextLines = (arg) => {
|
|
261
|
-
const { runs, fontSize, characterSpacing, boxWidthInPt } = arg;
|
|
262
|
-
const lines = [];
|
|
263
|
-
let currentLine = createLine();
|
|
264
|
-
const pushCurrentLine = (hardBreak) => {
|
|
265
|
-
currentLine.hardBreak = hardBreak;
|
|
266
|
-
lines.push(currentLine);
|
|
267
|
-
currentLine = createLine();
|
|
268
|
-
};
|
|
269
|
-
const pushPiecesToLine = (pieces) => {
|
|
270
|
-
pieces.forEach((piece) => {
|
|
271
|
-
pushRunToLine(currentLine, piece.run, piece.text, fontSize, characterSpacing);
|
|
272
|
-
});
|
|
273
|
-
};
|
|
274
|
-
const pushOversizedText = (run, text) => {
|
|
275
|
-
let remainingText = text;
|
|
276
|
-
while (remainingText.length > 0) {
|
|
277
|
-
const pendingSpacing = currentLine.runs.length > 0 ? characterSpacing : 0;
|
|
278
|
-
const remainingWidth = Math.max(boxWidthInPt - currentLine.width - pendingSpacing, 0);
|
|
279
|
-
const remainingTextWidth = measureRunText(run, remainingText, fontSize, characterSpacing);
|
|
280
|
-
if (remainingTextWidth <= remainingWidth || currentLine.runs.length === 0 && remainingTextWidth <= boxWidthInPt) {
|
|
281
|
-
pushRunToLine(currentLine, run, remainingText, fontSize, characterSpacing);
|
|
282
|
-
return;
|
|
283
|
-
}
|
|
284
|
-
if (currentLine.runs.length > 0 && remainingTextWidth <= boxWidthInPt) {
|
|
285
|
-
pushCurrentLine(false);
|
|
286
|
-
continue;
|
|
287
|
-
}
|
|
288
|
-
const graphemes = splitIntoGraphemes(remainingText);
|
|
289
|
-
let fittingText = "";
|
|
290
|
-
let fittingLength = 0;
|
|
291
|
-
for (const grapheme of graphemes) {
|
|
292
|
-
const candidate = fittingText + grapheme;
|
|
293
|
-
const candidateWidth = measureRunText(run, candidate, fontSize, characterSpacing);
|
|
294
|
-
const maxWidth = currentLine.runs.length === 0 ? boxWidthInPt : remainingWidth;
|
|
295
|
-
if (candidateWidth > maxWidth) {
|
|
296
|
-
if (fittingText) break;
|
|
297
|
-
if (currentLine.runs.length > 0) break;
|
|
298
|
-
}
|
|
299
|
-
fittingText = candidate;
|
|
300
|
-
fittingLength += grapheme.length;
|
|
301
|
-
if (candidateWidth > maxWidth) break;
|
|
302
|
-
}
|
|
303
|
-
if (!fittingText) {
|
|
304
|
-
pushCurrentLine(false);
|
|
305
|
-
continue;
|
|
306
|
-
}
|
|
307
|
-
pushRunToLine(currentLine, run, fittingText, fontSize, characterSpacing);
|
|
308
|
-
remainingText = remainingText.slice(fittingLength);
|
|
309
|
-
if (remainingText.length > 0) pushCurrentLine(false);
|
|
310
|
-
}
|
|
311
|
-
};
|
|
312
|
-
const pushSegment = (pieces) => {
|
|
313
|
-
const segmentWidth = measurePiecesWidth(pieces, fontSize, characterSpacing);
|
|
314
|
-
const pendingSpacing = currentLine.runs.length > 0 ? characterSpacing : 0;
|
|
315
|
-
if (segmentWidth <= Math.max(boxWidthInPt - currentLine.width - pendingSpacing, 0) || currentLine.runs.length === 0 && segmentWidth <= boxWidthInPt) {
|
|
316
|
-
pushPiecesToLine(pieces);
|
|
317
|
-
return;
|
|
318
|
-
}
|
|
319
|
-
if (currentLine.runs.length > 0) {
|
|
320
|
-
pushCurrentLine(false);
|
|
321
|
-
if (segmentWidth <= boxWidthInPt) {
|
|
322
|
-
pushPiecesToLine(pieces);
|
|
323
|
-
return;
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
pieces.forEach((piece) => pushOversizedText(piece.run, piece.text));
|
|
327
|
-
};
|
|
328
|
-
segmentRunPiecesByWord(runs, pushSegment, () => pushCurrentLine(true));
|
|
329
|
-
if (currentLine.runs.length > 0 || lines.length === 0) pushCurrentLine(false);
|
|
330
|
-
return lines;
|
|
331
|
-
};
|
|
332
|
-
var measureParagraphWidths = (runs, fontSize, characterSpacing) => {
|
|
333
|
-
const widths = [];
|
|
334
|
-
let paragraphPieces = [];
|
|
335
|
-
const pushWidth = () => {
|
|
336
|
-
widths.push(measurePiecesWidth(paragraphPieces, fontSize, characterSpacing));
|
|
337
|
-
paragraphPieces = [];
|
|
338
|
-
};
|
|
339
|
-
runs.forEach((run) => {
|
|
340
|
-
run.text.split(/(\r\n|\r|\n)/).forEach((part) => {
|
|
341
|
-
if (part === "\r\n" || part === "\r" || part === "\n") {
|
|
342
|
-
pushWidth();
|
|
343
|
-
return;
|
|
344
|
-
}
|
|
345
|
-
if (part) paragraphPieces.push({
|
|
346
|
-
run,
|
|
347
|
-
text: part
|
|
348
|
-
});
|
|
349
|
-
});
|
|
350
|
-
});
|
|
351
|
-
pushWidth();
|
|
352
|
-
return widths;
|
|
353
|
-
};
|
|
354
|
-
var getLineHeightAtSize = (line, fontSize) => {
|
|
355
|
-
if (line.runs.length === 0) return fontSize;
|
|
356
|
-
return Math.max(...line.runs.map((run) => heightOfFontAtSize(run.fontKitFont, fontSize)));
|
|
357
|
-
};
|
|
358
|
-
var calculateDynamicRichTextFontSize = async (arg) => {
|
|
359
|
-
const { value, schema, font, _cache, startingFontSize } = arg;
|
|
360
|
-
const { fontSize: schemaFontSize, dynamicFontSize: dynamicFontSizeSetting, characterSpacing: schemaCharacterSpacing, width: boxWidth, height: boxHeight, lineHeight = 1 } = schema;
|
|
361
|
-
const fontSize = startingFontSize || schemaFontSize || 13;
|
|
362
|
-
if (!dynamicFontSizeSetting) return fontSize;
|
|
363
|
-
if (dynamicFontSizeSetting.max < dynamicFontSizeSetting.min) return fontSize;
|
|
364
|
-
const resolvedRuns = await resolveRichTextRuns({
|
|
365
|
-
runs: parseInlineMarkdown(value),
|
|
366
|
-
schema,
|
|
367
|
-
font,
|
|
368
|
-
_cache
|
|
369
|
-
});
|
|
370
|
-
const characterSpacing = schemaCharacterSpacing ?? 0;
|
|
371
|
-
const dynamicFontFit = dynamicFontSizeSetting.fit ?? "vertical";
|
|
372
|
-
const boxWidthInPt = mm2pt(boxWidth);
|
|
373
|
-
let dynamicFontSize = fontSize;
|
|
374
|
-
if (dynamicFontSize < dynamicFontSizeSetting.min) dynamicFontSize = dynamicFontSizeSetting.min;
|
|
375
|
-
else if (dynamicFontSize > dynamicFontSizeSetting.max) dynamicFontSize = dynamicFontSizeSetting.max;
|
|
376
|
-
const calculateConstraints = (size) => {
|
|
377
|
-
let totalWidthInMm = 0;
|
|
378
|
-
let totalHeightInMm = 0;
|
|
379
|
-
layoutRichTextLines({
|
|
380
|
-
runs: resolvedRuns,
|
|
381
|
-
fontSize: size,
|
|
382
|
-
characterSpacing,
|
|
383
|
-
boxWidthInPt
|
|
384
|
-
}).forEach((line, lineIndex) => {
|
|
385
|
-
if (dynamicFontFit === "vertical") totalWidthInMm = Math.max(totalWidthInMm, pt2mm(line.width));
|
|
386
|
-
if (lineIndex === 0) totalHeightInMm += pt2mm(getLineHeightAtSize(line, size) * lineHeight);
|
|
387
|
-
else totalHeightInMm += pt2mm(size * lineHeight);
|
|
388
|
-
});
|
|
389
|
-
if (dynamicFontFit === "horizontal") measureParagraphWidths(resolvedRuns, size, characterSpacing).forEach((paragraphWidth) => {
|
|
390
|
-
totalWidthInMm = Math.max(totalWidthInMm, pt2mm(paragraphWidth));
|
|
391
|
-
});
|
|
392
|
-
return {
|
|
393
|
-
totalWidthInMm,
|
|
394
|
-
totalHeightInMm
|
|
395
|
-
};
|
|
396
|
-
};
|
|
397
|
-
const shouldFontGrowToFit = (totalWidthInMm, totalHeightInMm) => {
|
|
398
|
-
if (dynamicFontSize >= dynamicFontSizeSetting.max) return false;
|
|
399
|
-
if (dynamicFontFit === "horizontal") return totalWidthInMm < boxWidth;
|
|
400
|
-
return totalHeightInMm < boxHeight;
|
|
401
|
-
};
|
|
402
|
-
const shouldFontShrinkToFit = (totalWidthInMm, totalHeightInMm) => {
|
|
403
|
-
if (dynamicFontSize <= dynamicFontSizeSetting.min || dynamicFontSize <= 0) return false;
|
|
404
|
-
return totalWidthInMm > boxWidth || totalHeightInMm > boxHeight;
|
|
405
|
-
};
|
|
406
|
-
let { totalWidthInMm, totalHeightInMm } = calculateConstraints(dynamicFontSize);
|
|
407
|
-
while (shouldFontGrowToFit(totalWidthInMm, totalHeightInMm)) {
|
|
408
|
-
dynamicFontSize += FONT_SIZE_ADJUSTMENT;
|
|
409
|
-
const { totalWidthInMm: newWidth, totalHeightInMm: newHeight } = calculateConstraints(dynamicFontSize);
|
|
410
|
-
if (newHeight < boxHeight) {
|
|
411
|
-
totalWidthInMm = newWidth;
|
|
412
|
-
totalHeightInMm = newHeight;
|
|
413
|
-
} else {
|
|
414
|
-
dynamicFontSize -= FONT_SIZE_ADJUSTMENT;
|
|
415
|
-
break;
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
while (shouldFontShrinkToFit(totalWidthInMm, totalHeightInMm)) {
|
|
419
|
-
dynamicFontSize -= FONT_SIZE_ADJUSTMENT;
|
|
420
|
-
({totalWidthInMm, totalHeightInMm} = calculateConstraints(dynamicFontSize));
|
|
421
|
-
}
|
|
422
|
-
return dynamicFontSize;
|
|
33
|
+
page.node.addAnnot(annotationRef);
|
|
423
34
|
};
|
|
424
35
|
//#endregion
|
|
425
36
|
//#region src/text/richTextPdfRender.ts
|
|
426
37
|
var getSyntheticBoldWidth = (run, fontSize) => run.syntheticBold ? fontSize * SYNTHETIC_BOLD_OFFSET_RATIO * 2 : 0;
|
|
427
38
|
var getSyntheticItalicWidth = (run, fontSize) => run.syntheticItalic ? heightOfFontAtSize(run.fontKitFont, fontSize) * Math.tan(12 * Math.PI / 180) : 0;
|
|
428
39
|
var getRunWidth = (run, fontSize, characterSpacing) => widthOfTextAtSize(run.text, run.fontKitFont, fontSize, characterSpacing) + getSyntheticBoldWidth(run, fontSize) + getSyntheticItalicWidth(run, fontSize);
|
|
429
|
-
var
|
|
40
|
+
var getPdfFontFromObj = (run, pdfFontObj) => {
|
|
430
41
|
const pdfFont = pdfFontObj[run.fontName];
|
|
431
42
|
if (!pdfFont) throw new Error(`[@pdfme/schemas] Missing embedded font "${run.fontName}".`);
|
|
432
43
|
return pdfFont;
|
|
433
44
|
};
|
|
45
|
+
var embedFontsForRuns = async (runs, embedPdfFont) => {
|
|
46
|
+
const fontNames = Array.from(new Set(runs.map((run) => run.fontName)));
|
|
47
|
+
const pdfFonts = await Promise.all(fontNames.map(async (fontName) => [fontName, await embedPdfFont(fontName)]));
|
|
48
|
+
return Object.fromEntries(pdfFonts);
|
|
49
|
+
};
|
|
434
50
|
var drawDecorationLine = (arg) => {
|
|
435
51
|
const { page, x, y, width, rotate, pivotPoint, fontSize, color, opacity } = arg;
|
|
436
52
|
if (width <= 0) return;
|
|
@@ -448,8 +64,58 @@ var drawDecorationLine = (arg) => {
|
|
|
448
64
|
opacity
|
|
449
65
|
});
|
|
450
66
|
};
|
|
67
|
+
var getAxisAlignedRect = (arg) => {
|
|
68
|
+
const { x, y, width, height, rotate, pivotPoint } = arg;
|
|
69
|
+
if (rotate.angle === 0) return {
|
|
70
|
+
x,
|
|
71
|
+
y,
|
|
72
|
+
width,
|
|
73
|
+
height
|
|
74
|
+
};
|
|
75
|
+
const points = [
|
|
76
|
+
{
|
|
77
|
+
x,
|
|
78
|
+
y
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
x: x + width,
|
|
82
|
+
y
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
x: x + width,
|
|
86
|
+
y: y + height
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
x,
|
|
90
|
+
y: y + height
|
|
91
|
+
}
|
|
92
|
+
].map((point) => rotatePoint(point, pivotPoint, rotate.angle));
|
|
93
|
+
const xs = points.map((point) => point.x);
|
|
94
|
+
const ys = points.map((point) => point.y);
|
|
95
|
+
const minX = Math.min(...xs);
|
|
96
|
+
const minY = Math.min(...ys);
|
|
97
|
+
return {
|
|
98
|
+
x: minX,
|
|
99
|
+
y: minY,
|
|
100
|
+
width: Math.max(...xs) - minX,
|
|
101
|
+
height: Math.max(...ys) - minY
|
|
102
|
+
};
|
|
103
|
+
};
|
|
104
|
+
var getLinkAnnotationRect = (arg) => {
|
|
105
|
+
const { run, x, y, width, rotate, pivotPoint, fontSize } = arg;
|
|
106
|
+
const textHeight = heightOfFontAtSize(run.fontKitFont, fontSize);
|
|
107
|
+
const descent = getFontDescentInPt(run.fontKitFont, fontSize);
|
|
108
|
+
return getAxisAlignedRect({
|
|
109
|
+
x,
|
|
110
|
+
y: y + descent,
|
|
111
|
+
width,
|
|
112
|
+
height: textHeight - descent,
|
|
113
|
+
rotate,
|
|
114
|
+
pivotPoint
|
|
115
|
+
});
|
|
116
|
+
};
|
|
451
117
|
var drawRun = (arg) => {
|
|
452
|
-
const { page, pdfLib, run, pdfFont, x, y, rotate, pivotPoint, fontSize, lineHeight, color, opacity, colorType, characterSpacing, strikethrough } = arg;
|
|
118
|
+
const { page, pdfLib, run, pdfFont, x, y, rotate, pivotPoint, fontSize, lineHeight, color, opacity, colorType, characterSpacing, strikethrough, underline } = arg;
|
|
453
119
|
const runWidth = getRunWidth(run, fontSize, characterSpacing);
|
|
454
120
|
const textHeight = heightOfFontAtSize(run.fontKitFont, fontSize);
|
|
455
121
|
if (run.code) {
|
|
@@ -484,6 +150,17 @@ var drawRun = (arg) => {
|
|
|
484
150
|
color,
|
|
485
151
|
opacity
|
|
486
152
|
});
|
|
153
|
+
if (underline && runWidth > 0) drawDecorationLine({
|
|
154
|
+
page,
|
|
155
|
+
x,
|
|
156
|
+
y: y - textHeight / 12,
|
|
157
|
+
width: runWidth,
|
|
158
|
+
rotate,
|
|
159
|
+
pivotPoint,
|
|
160
|
+
fontSize,
|
|
161
|
+
color,
|
|
162
|
+
opacity
|
|
163
|
+
});
|
|
487
164
|
const drawAt = (drawX) => {
|
|
488
165
|
const point = rotate.angle === 0 ? {
|
|
489
166
|
x: drawX,
|
|
@@ -511,8 +188,8 @@ var drawRun = (arg) => {
|
|
|
511
188
|
}
|
|
512
189
|
};
|
|
513
190
|
var renderInlineMarkdownText = async (arg) => {
|
|
514
|
-
const { value, schema, font,
|
|
515
|
-
const
|
|
191
|
+
const { value, schema, font, embedPdfFont, fontKitFont, pdfDoc, page, pdfLib, _cache, colorType, fontSize, color, alignment, verticalAlignment, lineHeight, characterSpacing, x, width, height, pageHeight, pivotPoint, rotate, opacity } = arg;
|
|
192
|
+
const allLines = layoutRichTextLines({
|
|
516
193
|
runs: await resolveRichTextRuns({
|
|
517
194
|
runs: parseInlineMarkdown(value),
|
|
518
195
|
schema,
|
|
@@ -523,6 +200,10 @@ var renderInlineMarkdownText = async (arg) => {
|
|
|
523
200
|
characterSpacing,
|
|
524
201
|
boxWidthInPt: width
|
|
525
202
|
});
|
|
203
|
+
const lineRange = getTextLineRange(schema);
|
|
204
|
+
const lines = applyTextLineRange(allLines, lineRange);
|
|
205
|
+
const lineRangeStart = lineRange?.start ?? 0;
|
|
206
|
+
const pdfFontObj = await embedFontsForRuns(lines.flatMap((line) => line.runs), embedPdfFont);
|
|
526
207
|
const firstLineTextHeight = heightOfFontAtSize(fontKitFont, fontSize);
|
|
527
208
|
const descent = getFontDescentInPt(fontKitFont, fontSize);
|
|
528
209
|
const halfLineHeightAdjustment = lineHeight === 0 ? 0 : (lineHeight - 1) * fontSize / 2;
|
|
@@ -537,7 +218,7 @@ var renderInlineMarkdownText = async (arg) => {
|
|
|
537
218
|
if (line.runs.length === 0) return;
|
|
538
219
|
let textWidth = line.width;
|
|
539
220
|
let spacing = characterSpacing;
|
|
540
|
-
if (alignment === "justify" && !line.hardBreak && rowIndex <
|
|
221
|
+
if (alignment === "justify" && !line.hardBreak && lineRangeStart + rowIndex < allLines.length - 1) {
|
|
541
222
|
const graphemeCount = countRichTextLineGraphemes(line);
|
|
542
223
|
if (graphemeCount > 0) {
|
|
543
224
|
spacing += (width - textWidth) / graphemeCount;
|
|
@@ -580,7 +261,7 @@ var renderInlineMarkdownText = async (arg) => {
|
|
|
580
261
|
page,
|
|
581
262
|
pdfLib,
|
|
582
263
|
run,
|
|
583
|
-
pdfFont:
|
|
264
|
+
pdfFont: getPdfFontFromObj(run, pdfFontObj),
|
|
584
265
|
x: currentX,
|
|
585
266
|
y: yLine,
|
|
586
267
|
rotate,
|
|
@@ -591,28 +272,72 @@ var renderInlineMarkdownText = async (arg) => {
|
|
|
591
272
|
opacity,
|
|
592
273
|
colorType,
|
|
593
274
|
characterSpacing: spacing,
|
|
594
|
-
strikethrough: Boolean(run.strikethrough)
|
|
275
|
+
strikethrough: Boolean(run.strikethrough),
|
|
276
|
+
underline: Boolean(run.href) && !schema.underline
|
|
595
277
|
});
|
|
278
|
+
if (run.href) {
|
|
279
|
+
const rect = getLinkAnnotationRect({
|
|
280
|
+
run,
|
|
281
|
+
x: currentX,
|
|
282
|
+
y: yLine,
|
|
283
|
+
width: runWidth,
|
|
284
|
+
rotate,
|
|
285
|
+
pivotPoint,
|
|
286
|
+
fontSize
|
|
287
|
+
});
|
|
288
|
+
const targetName = getInternalLinkTarget(run.href);
|
|
289
|
+
if (targetName) registerInternalLinkAnnotation({
|
|
290
|
+
_cache,
|
|
291
|
+
page,
|
|
292
|
+
targetName,
|
|
293
|
+
rect
|
|
294
|
+
});
|
|
295
|
+
else addUriLinkAnnotation({
|
|
296
|
+
pdfDoc,
|
|
297
|
+
page,
|
|
298
|
+
uri: run.href,
|
|
299
|
+
rect
|
|
300
|
+
});
|
|
301
|
+
}
|
|
596
302
|
return currentX + runWidth + (runIndex === line.runs.length - 1 ? 0 : spacing);
|
|
597
303
|
}, xLine);
|
|
598
304
|
});
|
|
599
305
|
};
|
|
600
306
|
//#endregion
|
|
307
|
+
//#region src/text/overflow.ts
|
|
308
|
+
var TEXT_OVERFLOW_EXPAND_SCHEMA_TYPES = new Set(["text", "multiVariableText"]);
|
|
309
|
+
var isTextOverflowExpandSchema = (schema) => schema.type === void 0 || TEXT_OVERFLOW_EXPAND_SCHEMA_TYPES.has(schema.type);
|
|
310
|
+
var canUseTextOverflowExpand = (schema, basePdf) => !isTextOverflowExpandSchema(schema) || basePdf === void 0 || isBlankPdf(basePdf);
|
|
311
|
+
var isTextOverflowExpand = (schema, basePdf) => canUseTextOverflowExpand(schema, basePdf) && schema.overflow === "expand";
|
|
312
|
+
var shouldUseDynamicFontSize = (schema, basePdf) => Boolean(schema.dynamicFontSize) && !isTextOverflowExpand(schema, basePdf);
|
|
313
|
+
//#endregion
|
|
601
314
|
//#region src/text/pdfRender.ts
|
|
602
|
-
var
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
315
|
+
var PDF_FONT_CACHE_KEY = "text-pdf-font-cache";
|
|
316
|
+
var getPdfFontCache = (_cache) => {
|
|
317
|
+
let pdfFontCache = _cache.get(PDF_FONT_CACHE_KEY);
|
|
318
|
+
if (!pdfFontCache) {
|
|
319
|
+
pdfFontCache = {};
|
|
320
|
+
_cache.set(PDF_FONT_CACHE_KEY, pdfFontCache);
|
|
321
|
+
}
|
|
322
|
+
return pdfFontCache;
|
|
323
|
+
};
|
|
324
|
+
var embedAndGetFont = (arg) => {
|
|
325
|
+
const { pdfDoc, font, fontName, _cache } = arg;
|
|
326
|
+
const pdfFontCache = getPdfFontCache(_cache);
|
|
327
|
+
const cachedFont = pdfFontCache[fontName];
|
|
328
|
+
if (cachedFont) return cachedFont;
|
|
329
|
+
const fontValue = font[fontName];
|
|
330
|
+
if (!fontValue) return Promise.reject(/* @__PURE__ */ new Error(`[@pdfme/schemas] Font "${fontName}" is not found.`));
|
|
331
|
+
const pdfFontPromise = (async () => {
|
|
332
|
+
let fontData = fontValue.data;
|
|
607
333
|
if (typeof fontData === "string" && fontData.startsWith("http")) fontData = await fetchRemoteFontData(fontData);
|
|
608
|
-
return pdfDoc.embedFont(fontData, { subset: typeof
|
|
609
|
-
}));
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
return fontObj;
|
|
334
|
+
return pdfDoc.embedFont(fontData, { subset: typeof fontValue.subset === "undefined" ? true : fontValue.subset });
|
|
335
|
+
})();
|
|
336
|
+
pdfFontCache[fontName] = pdfFontPromise;
|
|
337
|
+
return pdfFontPromise;
|
|
613
338
|
};
|
|
614
|
-
var getFontProp = ({ value, fontKitFont, schema, colorType, fontSize: resolvedFontSize }) => {
|
|
615
|
-
const fontSize = resolvedFontSize ?? (schema
|
|
339
|
+
var getFontProp = ({ value, fontKitFont, schema, basePdf, colorType, fontSize: resolvedFontSize }) => {
|
|
340
|
+
const fontSize = resolvedFontSize ?? (shouldUseDynamicFontSize(schema, basePdf) ? calculateDynamicFontSize({
|
|
616
341
|
textSchema: schema,
|
|
617
342
|
fontKitFont,
|
|
618
343
|
value
|
|
@@ -627,30 +352,37 @@ var getFontProp = ({ value, fontKitFont, schema, colorType, fontSize: resolvedFo
|
|
|
627
352
|
color
|
|
628
353
|
};
|
|
629
354
|
};
|
|
355
|
+
var graphemeSegmenter;
|
|
356
|
+
var getGraphemeSegmenter = () => {
|
|
357
|
+
graphemeSegmenter ?? (graphemeSegmenter = new Intl.Segmenter(void 0, { granularity: "grapheme" }));
|
|
358
|
+
return graphemeSegmenter;
|
|
359
|
+
};
|
|
630
360
|
var pdfRender = async (arg) => {
|
|
631
|
-
const { value, pdfDoc, pdfLib, page, options, schema, _cache } = arg;
|
|
361
|
+
const { value, pdfDoc, pdfLib, page, options, schema, basePdf, _cache } = arg;
|
|
632
362
|
if (!value) return;
|
|
633
363
|
const { font = getDefaultFont(), colorType } = options;
|
|
634
|
-
const
|
|
364
|
+
const fontName = schema.fontName ? schema.fontName : getFallbackFontName(font);
|
|
365
|
+
const enableInlineMarkdown = isInlineMarkdownTextSchema(schema);
|
|
366
|
+
const pdfFontValuePromise = enableInlineMarkdown ? void 0 : embedAndGetFont({
|
|
635
367
|
pdfDoc,
|
|
636
368
|
font,
|
|
369
|
+
fontName,
|
|
637
370
|
_cache
|
|
638
|
-
})
|
|
639
|
-
const
|
|
371
|
+
});
|
|
372
|
+
const fontKitFont = await getFontKitFont(schema.fontName, font, _cache);
|
|
640
373
|
const { fontSize, color, alignment, verticalAlignment, lineHeight, characterSpacing } = getFontProp({
|
|
641
374
|
value: enableInlineMarkdown ? stripInlineMarkdown(value) : value,
|
|
642
375
|
fontKitFont,
|
|
643
376
|
schema,
|
|
377
|
+
basePdf,
|
|
644
378
|
colorType,
|
|
645
|
-
fontSize: enableInlineMarkdown && schema
|
|
379
|
+
fontSize: enableInlineMarkdown && shouldUseDynamicFontSize(schema, basePdf) ? await calculateDynamicRichTextFontSize({
|
|
646
380
|
value,
|
|
647
381
|
schema,
|
|
648
382
|
font,
|
|
649
383
|
_cache
|
|
650
384
|
}) : void 0
|
|
651
385
|
});
|
|
652
|
-
const fontName = schema.fontName ? schema.fontName : getFallbackFontName(font);
|
|
653
|
-
const pdfFontValue = pdfFontObj && pdfFontObj[fontName];
|
|
654
386
|
const pageHeight = page.getHeight();
|
|
655
387
|
const { width, height, rotate, position: { x, y }, opacity } = convertForPdfLayoutProps({
|
|
656
388
|
schema,
|
|
@@ -690,8 +422,14 @@ var pdfRender = async (arg) => {
|
|
|
690
422
|
value,
|
|
691
423
|
schema,
|
|
692
424
|
font,
|
|
693
|
-
|
|
425
|
+
embedPdfFont: (fontName) => embedAndGetFont({
|
|
426
|
+
pdfDoc,
|
|
427
|
+
font,
|
|
428
|
+
fontName,
|
|
429
|
+
_cache
|
|
430
|
+
}),
|
|
694
431
|
fontKitFont,
|
|
432
|
+
pdfDoc,
|
|
695
433
|
page,
|
|
696
434
|
pdfLib,
|
|
697
435
|
_cache,
|
|
@@ -712,16 +450,20 @@ var pdfRender = async (arg) => {
|
|
|
712
450
|
});
|
|
713
451
|
return;
|
|
714
452
|
}
|
|
453
|
+
if (!pdfFontValuePromise) throw new Error("[@pdfme/schemas] Failed to prepare PDF font for text rendering.");
|
|
454
|
+
const pdfFontValue = await pdfFontValuePromise;
|
|
715
455
|
const firstLineTextHeight = heightOfFontAtSize(fontKitFont, fontSize);
|
|
716
456
|
const descent = getFontDescentInPt(fontKitFont, fontSize);
|
|
717
457
|
const halfLineHeightAdjustment = lineHeight === 0 ? 0 : (lineHeight - 1) * fontSize / 2;
|
|
718
|
-
const lines = splitTextToSize({
|
|
458
|
+
const lines = applyTextLineRange(splitTextToSize({
|
|
719
459
|
value,
|
|
720
460
|
characterSpacing,
|
|
721
461
|
fontSize,
|
|
722
462
|
fontKitFont,
|
|
723
463
|
boxWidthInPt: width
|
|
724
|
-
});
|
|
464
|
+
}), getTextLineRange(schema));
|
|
465
|
+
const needsTextWidth = alignment !== "left" || Boolean(schema.strikethrough || schema.underline);
|
|
466
|
+
const needsTextHeight = Boolean(schema.strikethrough || schema.underline);
|
|
725
467
|
let yOffset = 0;
|
|
726
468
|
if (verticalAlignment === "top") yOffset = firstLineTextHeight + halfLineHeightAdjustment;
|
|
727
469
|
else {
|
|
@@ -729,11 +471,10 @@ var pdfRender = async (arg) => {
|
|
|
729
471
|
if (verticalAlignment === "bottom") yOffset = height - otherLinesHeight + descent - halfLineHeightAdjustment;
|
|
730
472
|
else if (verticalAlignment === "middle") yOffset = (height - otherLinesHeight - firstLineTextHeight + descent) / 2 + firstLineTextHeight;
|
|
731
473
|
}
|
|
732
|
-
const segmenter = new Intl.Segmenter(void 0, { granularity: "grapheme" });
|
|
733
474
|
lines.forEach((line, rowIndex) => {
|
|
734
475
|
const trimmed = line.replace("\n", "");
|
|
735
|
-
const textWidth = widthOfTextAtSize(trimmed, fontKitFont, fontSize, characterSpacing);
|
|
736
|
-
const textHeight = heightOfFontAtSize(fontKitFont, fontSize);
|
|
476
|
+
const textWidth = needsTextWidth ? widthOfTextAtSize(trimmed, fontKitFont, fontSize, characterSpacing) : 0;
|
|
477
|
+
const textHeight = needsTextHeight ? heightOfFontAtSize(fontKitFont, fontSize) : 0;
|
|
737
478
|
const rowYOffset = lineHeight * fontSize * rowIndex;
|
|
738
479
|
if (line === "") line = "\r\n";
|
|
739
480
|
let xLine = x;
|
|
@@ -784,7 +525,7 @@ var pdfRender = async (arg) => {
|
|
|
784
525
|
}
|
|
785
526
|
let spacing = characterSpacing;
|
|
786
527
|
if (alignment === "justify" && line.slice(-1) !== "\n") {
|
|
787
|
-
const iterator =
|
|
528
|
+
const iterator = getGraphemeSegmenter().segment(trimmed)[Symbol.iterator]();
|
|
788
529
|
const len = Array.from(iterator).length;
|
|
789
530
|
spacing += (width - textWidth) / len;
|
|
790
531
|
}
|
|
@@ -886,10 +627,12 @@ function getExtraFormatterSchema(i18n) {
|
|
|
886
627
|
//#endregion
|
|
887
628
|
//#region src/text/propPanel.ts
|
|
888
629
|
var UseDynamicFontSize = (props) => {
|
|
889
|
-
const { rootElement, changeSchemas, activeSchema, i18n } = props;
|
|
630
|
+
const { rootElement, changeSchemas, activeSchema, i18n, basePdf } = props;
|
|
631
|
+
const isExpand = isTextOverflowExpand(activeSchema, basePdf);
|
|
890
632
|
const checkbox = document.createElement("input");
|
|
891
633
|
checkbox.type = "checkbox";
|
|
892
|
-
checkbox.checked = Boolean(activeSchema?.dynamicFontSize);
|
|
634
|
+
checkbox.checked = !isExpand && Boolean(activeSchema?.dynamicFontSize);
|
|
635
|
+
checkbox.disabled = isExpand;
|
|
893
636
|
checkbox.onchange = (e) => {
|
|
894
637
|
changeSchemas([{
|
|
895
638
|
key: "dynamicFontSize",
|
|
@@ -906,6 +649,7 @@ var UseDynamicFontSize = (props) => {
|
|
|
906
649
|
span.innerText = i18n("schemas.text.dynamicFontSize") || "";
|
|
907
650
|
span.style.cssText = "margin-left: 0.5rem";
|
|
908
651
|
label.style.cssText = "display: flex; width: 100%;";
|
|
652
|
+
label.style.opacity = isExpand ? "0.5" : "1";
|
|
909
653
|
label.appendChild(checkbox);
|
|
910
654
|
label.appendChild(span);
|
|
911
655
|
rootElement.appendChild(label);
|
|
@@ -932,15 +676,16 @@ var UseInlineMarkdown = (props) => {
|
|
|
932
676
|
rootElement.appendChild(label);
|
|
933
677
|
};
|
|
934
678
|
var propPanel = {
|
|
935
|
-
schema: ({ options, activeSchema, i18n }) => {
|
|
679
|
+
schema: ({ options, activeSchema, i18n, basePdf }) => {
|
|
936
680
|
const font = options.font || { [DEFAULT_FONT_NAME]: {
|
|
937
681
|
data: "",
|
|
938
682
|
fallback: true
|
|
939
683
|
} };
|
|
940
684
|
const fontNames = Object.keys(font);
|
|
941
685
|
const fallbackFontName = getFallbackFontName(font);
|
|
942
|
-
const enableDynamicFont = Boolean(activeSchema?.dynamicFontSize);
|
|
943
686
|
const activeTextSchema = activeSchema;
|
|
687
|
+
const canExpandOverflow = canUseTextOverflowExpand(activeTextSchema, basePdf);
|
|
688
|
+
const enableDynamicFont = !isTextOverflowExpand(activeTextSchema, basePdf) && Boolean(activeSchema?.dynamicFontSize);
|
|
944
689
|
const hideTextFormat = activeTextSchema.type === "text" && activeTextSchema.readOnly !== true;
|
|
945
690
|
const enableInlineMarkdown = activeTextSchema.textFormat === "inline-markdown" && !hideTextFormat;
|
|
946
691
|
const baseFontName = activeTextSchema.fontName && font[activeTextSchema.fontName] ? activeTextSchema.fontName : fallbackFontName;
|
|
@@ -951,6 +696,13 @@ var propPanel = {
|
|
|
951
696
|
label: name,
|
|
952
697
|
value: name
|
|
953
698
|
}))];
|
|
699
|
+
const overflowOptions = [{
|
|
700
|
+
label: i18n("schemas.text.overflowVisible"),
|
|
701
|
+
value: TEXT_OVERFLOW_VISIBLE
|
|
702
|
+
}, ...canExpandOverflow ? [{
|
|
703
|
+
label: i18n("schemas.text.overflowExpand"),
|
|
704
|
+
value: TEXT_OVERFLOW_EXPAND
|
|
705
|
+
}] : []];
|
|
954
706
|
return {
|
|
955
707
|
fontName: {
|
|
956
708
|
title: i18n("schemas.text.fontName"),
|
|
@@ -990,6 +742,14 @@ var propPanel = {
|
|
|
990
742
|
},
|
|
991
743
|
span: 8
|
|
992
744
|
},
|
|
745
|
+
overflow: {
|
|
746
|
+
title: i18n("schemas.text.overflow"),
|
|
747
|
+
type: "string",
|
|
748
|
+
widget: "select",
|
|
749
|
+
default: DEFAULT_TEXT_OVERFLOW,
|
|
750
|
+
props: { options: overflowOptions },
|
|
751
|
+
span: 8
|
|
752
|
+
},
|
|
993
753
|
useDynamicFontSize: {
|
|
994
754
|
type: "boolean",
|
|
995
755
|
widget: "UseDynamicFontSize",
|
|
@@ -1133,6 +893,7 @@ var propPanel = {
|
|
|
1133
893
|
verticalAlignment: "top",
|
|
1134
894
|
fontSize: 13,
|
|
1135
895
|
textFormat: DEFAULT_TEXT_FORMAT,
|
|
896
|
+
overflow: DEFAULT_TEXT_OVERFLOW,
|
|
1136
897
|
fontVariantFallback: DEFAULT_FONT_VARIANT_FALLBACK,
|
|
1137
898
|
lineHeight: 1,
|
|
1138
899
|
characterSpacing: 0,
|
|
@@ -1164,8 +925,13 @@ var replaceUnsupportedChars = (text, fontKitFont) => {
|
|
|
1164
925
|
}).join("");
|
|
1165
926
|
};
|
|
1166
927
|
var uiRender = async (arg) => {
|
|
1167
|
-
const { value, schema, mode, onChange, stopEditing, tabIndex, placeholder, options, _cache } = arg;
|
|
1168
|
-
const
|
|
928
|
+
const { value, schema, basePdf, mode, onChange, stopEditing, tabIndex, placeholder, options, _cache } = arg;
|
|
929
|
+
const hasInlineMarkdownFormat = schema.textFormat === TEXT_FORMAT_INLINE_MARKDOWN;
|
|
930
|
+
const enableInlineMarkdown = isInlineMarkdownTextSchema(schema);
|
|
931
|
+
const isReadOnlySplitInlineMarkdownFormChunk = mode === "form" && Boolean(getTextLineRange(schema)) && hasInlineMarkdownFormat;
|
|
932
|
+
const renderInlineMarkdownReadOnlyChunk = enableInlineMarkdown || isReadOnlySplitInlineMarkdownFormChunk;
|
|
933
|
+
const editable = isEditable(mode, schema) && !isReadOnlySplitInlineMarkdownFormChunk;
|
|
934
|
+
const usePlaceholder = editable && placeholder && !value;
|
|
1169
935
|
const getText = (element) => {
|
|
1170
936
|
let text = element.innerText;
|
|
1171
937
|
if (text.endsWith("\n")) text = text.slice(0, -1);
|
|
@@ -1173,18 +939,26 @@ var uiRender = async (arg) => {
|
|
|
1173
939
|
};
|
|
1174
940
|
const font = options?.font || getDefaultFont();
|
|
1175
941
|
const fontKitFont = await getFontKitFont(schema.fontName, font, _cache);
|
|
1176
|
-
const
|
|
942
|
+
const enableDynamicFontSize = shouldUseDynamicFontSize(schema, basePdf);
|
|
1177
943
|
const displayValue = enableInlineMarkdown ? stripInlineMarkdown(value) : value;
|
|
1178
|
-
const dynamicRichTextFontSize = enableInlineMarkdown &&
|
|
944
|
+
const dynamicRichTextFontSize = enableInlineMarkdown && enableDynamicFontSize ? await calculateDynamicRichTextFontSize({
|
|
1179
945
|
value: usePlaceholder ? placeholder : value,
|
|
1180
946
|
schema,
|
|
1181
947
|
font,
|
|
1182
948
|
_cache
|
|
1183
949
|
}) : void 0;
|
|
1184
|
-
const textBlock = buildStyledTextContainer(
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
950
|
+
const textBlock = buildStyledTextContainer(isReadOnlySplitInlineMarkdownFormChunk ? {
|
|
951
|
+
...arg,
|
|
952
|
+
mode: "viewer"
|
|
953
|
+
} : arg, fontKitFont, usePlaceholder ? placeholder : displayValue, dynamicRichTextFontSize);
|
|
954
|
+
const processedText = replaceUnsupportedChars(getRangedPlainTextValue({
|
|
955
|
+
value,
|
|
956
|
+
schema,
|
|
957
|
+
fontKitFont,
|
|
958
|
+
fontSize: schema.fontSize ?? 13
|
|
959
|
+
}), fontKitFont);
|
|
960
|
+
if (!editable) {
|
|
961
|
+
if (renderInlineMarkdownReadOnlyChunk) {
|
|
1188
962
|
await renderInlineMarkdownReadOnly({
|
|
1189
963
|
textBlock,
|
|
1190
964
|
value,
|
|
@@ -1210,7 +984,7 @@ var uiRender = async (arg) => {
|
|
|
1210
984
|
});
|
|
1211
985
|
if (stopEditing) stopEditing();
|
|
1212
986
|
});
|
|
1213
|
-
if (
|
|
987
|
+
if (enableDynamicFontSize) {
|
|
1214
988
|
let dynamicFontSize = void 0;
|
|
1215
989
|
textBlock.addEventListener("keyup", () => {
|
|
1216
990
|
setTimeout(() => {
|
|
@@ -1259,30 +1033,86 @@ var renderInlineMarkdownReadOnly = async (arg) => {
|
|
|
1259
1033
|
font,
|
|
1260
1034
|
_cache
|
|
1261
1035
|
});
|
|
1036
|
+
const lineRange = getTextLineRange(schema);
|
|
1037
|
+
if (lineRange) {
|
|
1038
|
+
const lines = applyTextLineRange(layoutRichTextLines({
|
|
1039
|
+
runs,
|
|
1040
|
+
fontSize: schema.fontSize ?? 13,
|
|
1041
|
+
characterSpacing: schema.characterSpacing ?? 0,
|
|
1042
|
+
boxWidthInPt: mm2pt(schema.width)
|
|
1043
|
+
}), lineRange);
|
|
1044
|
+
textBlock.innerHTML = "";
|
|
1045
|
+
lines.forEach((line, lineIndex) => {
|
|
1046
|
+
line.runs.forEach((run) => {
|
|
1047
|
+
appendInlineMarkdownRun({
|
|
1048
|
+
textBlock,
|
|
1049
|
+
run,
|
|
1050
|
+
schema,
|
|
1051
|
+
font
|
|
1052
|
+
});
|
|
1053
|
+
});
|
|
1054
|
+
if (lineIndex < lines.length - 1) textBlock.appendChild(document.createElement("br"));
|
|
1055
|
+
});
|
|
1056
|
+
return;
|
|
1057
|
+
}
|
|
1262
1058
|
textBlock.innerHTML = "";
|
|
1263
1059
|
runs.forEach((run) => {
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
}
|
|
1271
|
-
if (run.syntheticItalic) span.style.fontStyle = "italic";
|
|
1272
|
-
if (run.strikethrough) span.style.textDecoration = "line-through";
|
|
1273
|
-
if (run.code) {
|
|
1274
|
-
span.style.backgroundColor = CODE_BACKGROUND_COLOR;
|
|
1275
|
-
span.style.borderRadius = "2px";
|
|
1276
|
-
span.style.padding = "0 0.15em";
|
|
1277
|
-
if (!schema.fontVariants?.code || !font[schema.fontVariants.code]) span.style.fontFamily = run.fontName ? `'${run.fontName}', monospace` : "monospace";
|
|
1278
|
-
}
|
|
1279
|
-
textBlock.appendChild(span);
|
|
1060
|
+
appendInlineMarkdownRun({
|
|
1061
|
+
textBlock,
|
|
1062
|
+
run,
|
|
1063
|
+
schema,
|
|
1064
|
+
font
|
|
1065
|
+
});
|
|
1280
1066
|
});
|
|
1281
1067
|
};
|
|
1068
|
+
var appendInlineMarkdownRun = (arg) => {
|
|
1069
|
+
const { textBlock, run, schema, font } = arg;
|
|
1070
|
+
const href = run.href ? normalizeLinkHref(run.href) : void 0;
|
|
1071
|
+
const span = href ? document.createElement("a") : document.createElement("span");
|
|
1072
|
+
const processedText = replaceUnsupportedChars(run.text, run.fontKitFont);
|
|
1073
|
+
const textDecorations = [];
|
|
1074
|
+
span.textContent = processedText;
|
|
1075
|
+
if (href) {
|
|
1076
|
+
const anchor = span;
|
|
1077
|
+
anchor.href = href;
|
|
1078
|
+
if (!getInternalLinkTarget(href)) {
|
|
1079
|
+
anchor.target = "_blank";
|
|
1080
|
+
anchor.rel = "noopener noreferrer";
|
|
1081
|
+
}
|
|
1082
|
+
textDecorations.push("underline");
|
|
1083
|
+
}
|
|
1084
|
+
if (run.fontName) span.style.fontFamily = `'${run.fontName}'`;
|
|
1085
|
+
if (run.syntheticBold) {
|
|
1086
|
+
span.style.fontWeight = "800";
|
|
1087
|
+
span.style.textShadow = SYNTHETIC_BOLD_CSS_TEXT_SHADOW;
|
|
1088
|
+
}
|
|
1089
|
+
if (run.syntheticItalic) span.style.fontStyle = "italic";
|
|
1090
|
+
if (run.strikethrough) textDecorations.push("line-through");
|
|
1091
|
+
if (textDecorations.length > 0) span.style.textDecoration = textDecorations.join(" ");
|
|
1092
|
+
if (run.code) {
|
|
1093
|
+
span.style.backgroundColor = CODE_BACKGROUND_COLOR;
|
|
1094
|
+
span.style.borderRadius = "2px";
|
|
1095
|
+
span.style.padding = "0 0.15em";
|
|
1096
|
+
if (!schema.fontVariants?.code || !font[schema.fontVariants.code]) span.style.fontFamily = run.fontName ? `'${run.fontName}', monospace` : "monospace";
|
|
1097
|
+
}
|
|
1098
|
+
textBlock.appendChild(span);
|
|
1099
|
+
};
|
|
1100
|
+
var getRangedPlainTextValue = (arg) => {
|
|
1101
|
+
const { value, schema, fontKitFont, fontSize } = arg;
|
|
1102
|
+
const lineRange = getTextLineRange(schema);
|
|
1103
|
+
if (!lineRange) return value;
|
|
1104
|
+
return plainTextLinesToValue(applyTextLineRange(splitTextToSize({
|
|
1105
|
+
value,
|
|
1106
|
+
characterSpacing: schema.characterSpacing ?? 0,
|
|
1107
|
+
fontSize,
|
|
1108
|
+
fontKitFont,
|
|
1109
|
+
boxWidthInPt: mm2pt(schema.width)
|
|
1110
|
+
}), lineRange));
|
|
1111
|
+
};
|
|
1282
1112
|
var buildStyledTextContainer = (arg, fontKitFont, value, resolvedDynamicFontSize) => {
|
|
1283
1113
|
const { schema, rootElement, mode } = arg;
|
|
1284
1114
|
let dynamicFontSize = resolvedDynamicFontSize;
|
|
1285
|
-
if (dynamicFontSize === void 0 && schema.
|
|
1115
|
+
if (dynamicFontSize === void 0 && shouldUseDynamicFontSize(schema, arg.basePdf) && value) dynamicFontSize = calculateDynamicFontSize({
|
|
1286
1116
|
textSchema: schema,
|
|
1287
1117
|
fontKitFont,
|
|
1288
1118
|
value,
|
|
@@ -1383,6 +1213,6 @@ var textSchema = {
|
|
|
1383
1213
|
//#region src/builtins.ts
|
|
1384
1214
|
var builtInPlugins = { Text: textSchema };
|
|
1385
1215
|
//#endregion
|
|
1386
|
-
export { mapVerticalAlignToFlex as a, Formatter as c,
|
|
1216
|
+
export { mapVerticalAlignToFlex as a, Formatter as c, makeElementPlainTextContentEditable as i, getExtraFormatterSchema as l, textSchema as n, uiRender as o, buildStyledTextContainer as r, propPanel as s, builtInPlugins as t, pdfRender as u };
|
|
1387
1217
|
|
|
1388
|
-
//# sourceMappingURL=builtins-
|
|
1218
|
+
//# sourceMappingURL=builtins-Clh58o_b.js.map
|