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