@jsonpdf/plugins 0.1.0-alpha.1
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/LICENSE +21 -0
- package/README.md +59 -0
- package/dist/barcode/barcode-generator.d.ts +18 -0
- package/dist/barcode/barcode-generator.d.ts.map +1 -0
- package/dist/barcode/barcode-generator.js +94 -0
- package/dist/barcode/barcode-generator.js.map +1 -0
- package/dist/barcode/barcode-plugin.d.ts +4 -0
- package/dist/barcode/barcode-plugin.d.ts.map +1 -0
- package/dist/barcode/barcode-plugin.js +70 -0
- package/dist/barcode/barcode-plugin.js.map +1 -0
- package/dist/barcode/barcode-types.d.ts +29 -0
- package/dist/barcode/barcode-types.d.ts.map +1 -0
- package/dist/barcode/barcode-types.js +60 -0
- package/dist/barcode/barcode-types.js.map +1 -0
- package/dist/chart/chart-generator.d.ts +17 -0
- package/dist/chart/chart-generator.d.ts.map +1 -0
- package/dist/chart/chart-generator.js +77 -0
- package/dist/chart/chart-generator.js.map +1 -0
- package/dist/chart/chart-plugin.d.ts +4 -0
- package/dist/chart/chart-plugin.d.ts.map +1 -0
- package/dist/chart/chart-plugin.js +65 -0
- package/dist/chart/chart-plugin.js.map +1 -0
- package/dist/chart/chart-types.d.ts +18 -0
- package/dist/chart/chart-types.d.ts.map +1 -0
- package/dist/chart/chart-types.js +18 -0
- package/dist/chart/chart-types.js.map +1 -0
- package/dist/container/container-plugin.d.ts +15 -0
- package/dist/container/container-plugin.d.ts.map +1 -0
- package/dist/container/container-plugin.js +190 -0
- package/dist/container/container-plugin.js.map +1 -0
- package/dist/frame/frame-plugin.d.ts +4 -0
- package/dist/frame/frame-plugin.d.ts.map +1 -0
- package/dist/frame/frame-plugin.js +52 -0
- package/dist/frame/frame-plugin.js.map +1 -0
- package/dist/frame/frame-types.d.ts +8 -0
- package/dist/frame/frame-types.d.ts.map +1 -0
- package/dist/frame/frame-types.js +17 -0
- package/dist/frame/frame-types.js.map +1 -0
- package/dist/image/image-loader.d.ts +13 -0
- package/dist/image/image-loader.d.ts.map +1 -0
- package/dist/image/image-loader.js +73 -0
- package/dist/image/image-loader.js.map +1 -0
- package/dist/image/image-plugin.d.ts +19 -0
- package/dist/image/image-plugin.d.ts.map +1 -0
- package/dist/image/image-plugin.js +112 -0
- package/dist/image/image-plugin.js.map +1 -0
- package/dist/image/svg-rasterizer.d.ts +30 -0
- package/dist/image/svg-rasterizer.d.ts.map +1 -0
- package/dist/image/svg-rasterizer.js +97 -0
- package/dist/image/svg-rasterizer.js.map +1 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +38 -0
- package/dist/index.js.map +1 -0
- package/dist/line/line-plugin.d.ts +11 -0
- package/dist/line/line-plugin.d.ts.map +1 -0
- package/dist/line/line-plugin.js +68 -0
- package/dist/line/line-plugin.js.map +1 -0
- package/dist/list/list-plugin.d.ts +13 -0
- package/dist/list/list-plugin.d.ts.map +1 -0
- package/dist/list/list-plugin.js +194 -0
- package/dist/list/list-plugin.js.map +1 -0
- package/dist/list/list-types.d.ts +9 -0
- package/dist/list/list-types.d.ts.map +1 -0
- package/dist/list/list-types.js +9 -0
- package/dist/list/list-types.js.map +1 -0
- package/dist/platform/base64.d.ts +7 -0
- package/dist/platform/base64.d.ts.map +1 -0
- package/dist/platform/base64.js +17 -0
- package/dist/platform/base64.js.map +1 -0
- package/dist/platform/font-store.d.ts +3 -0
- package/dist/platform/font-store.d.ts.map +1 -0
- package/dist/platform/font-store.js +8 -0
- package/dist/platform/font-store.js.map +1 -0
- package/dist/platform/fs.browser.d.ts +6 -0
- package/dist/platform/fs.browser.d.ts.map +1 -0
- package/dist/platform/fs.browser.js +10 -0
- package/dist/platform/fs.browser.js.map +1 -0
- package/dist/platform/fs.d.ts +5 -0
- package/dist/platform/fs.d.ts.map +1 -0
- package/dist/platform/fs.js +10 -0
- package/dist/platform/fs.js.map +1 -0
- package/dist/platform/init.browser.d.ts +10 -0
- package/dist/platform/init.browser.d.ts.map +1 -0
- package/dist/platform/init.browser.js +24 -0
- package/dist/platform/init.browser.js.map +1 -0
- package/dist/platform/init.d.ts +6 -0
- package/dist/platform/init.d.ts.map +1 -0
- package/dist/platform/init.js +12 -0
- package/dist/platform/init.js.map +1 -0
- package/dist/platform/svg-rasterizer.browser.d.ts +2 -0
- package/dist/platform/svg-rasterizer.browser.d.ts.map +1 -0
- package/dist/platform/svg-rasterizer.browser.js +2 -0
- package/dist/platform/svg-rasterizer.browser.js.map +1 -0
- package/dist/platform/svg-rasterizer.d.ts +2 -0
- package/dist/platform/svg-rasterizer.d.ts.map +1 -0
- package/dist/platform/svg-rasterizer.js +2 -0
- package/dist/platform/svg-rasterizer.js.map +1 -0
- package/dist/registry.d.ts +32 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +67 -0
- package/dist/registry.js.map +1 -0
- package/dist/shape/shape-plugin.d.ts +21 -0
- package/dist/shape/shape-plugin.d.ts.map +1 -0
- package/dist/shape/shape-plugin.js +148 -0
- package/dist/shape/shape-plugin.js.map +1 -0
- package/dist/table/table-plugin.d.ts +4 -0
- package/dist/table/table-plugin.d.ts.map +1 -0
- package/dist/table/table-plugin.js +232 -0
- package/dist/table/table-plugin.js.map +1 -0
- package/dist/table/table-types.d.ts +50 -0
- package/dist/table/table-types.d.ts.map +1 -0
- package/dist/table/table-types.js +129 -0
- package/dist/table/table-types.js.map +1 -0
- package/dist/text/text-decoration.d.ts +22 -0
- package/dist/text/text-decoration.d.ts.map +1 -0
- package/dist/text/text-decoration.js +43 -0
- package/dist/text/text-decoration.js.map +1 -0
- package/dist/text/text-plugin.d.ts +9 -0
- package/dist/text/text-plugin.d.ts.map +1 -0
- package/dist/text/text-plugin.js +496 -0
- package/dist/text/text-plugin.js.map +1 -0
- package/dist/text/word-wrap.d.ts +41 -0
- package/dist/text/word-wrap.d.ts.map +1 -0
- package/dist/text/word-wrap.js +149 -0
- package/dist/text/word-wrap.js.map +1 -0
- package/dist/types.d.ts +96 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/dist/utils.d.ts +8 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +27 -0
- package/dist/utils.js.map +1 -0
- package/package.json +62 -0
|
@@ -0,0 +1,496 @@
|
|
|
1
|
+
import { rgb, PDFName, PDFString, PDFArray, PDFRef, pushGraphicsState, popGraphicsState, setWordSpacing, setCharacterSpacing, } from 'pdf-lib';
|
|
2
|
+
import { parseColor } from '@jsonpdf/core';
|
|
3
|
+
import { getFont, getLineHeight } from '../utils.js';
|
|
4
|
+
import { wrapText, measureTextWidth, splitWrappedText } from './word-wrap.js';
|
|
5
|
+
import { drawTextDecoration } from './text-decoration.js';
|
|
6
|
+
export const textPropsSchema = {
|
|
7
|
+
type: 'object',
|
|
8
|
+
required: ['content'],
|
|
9
|
+
properties: {
|
|
10
|
+
content: {
|
|
11
|
+
oneOf: [
|
|
12
|
+
{ type: 'string' },
|
|
13
|
+
{
|
|
14
|
+
type: 'array',
|
|
15
|
+
items: {
|
|
16
|
+
type: 'object',
|
|
17
|
+
required: ['text'],
|
|
18
|
+
properties: {
|
|
19
|
+
text: { type: 'string' },
|
|
20
|
+
style: { type: 'string' },
|
|
21
|
+
styleOverrides: { type: 'object' },
|
|
22
|
+
link: { type: 'string' },
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
],
|
|
27
|
+
},
|
|
28
|
+
autoHeight: { type: 'boolean' },
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
const TEXT_DEFAULTS = { content: '' };
|
|
32
|
+
export const textPlugin = {
|
|
33
|
+
type: 'text',
|
|
34
|
+
propsSchema: textPropsSchema,
|
|
35
|
+
defaultProps: TEXT_DEFAULTS,
|
|
36
|
+
resolveProps(raw) {
|
|
37
|
+
return { ...TEXT_DEFAULTS, ...raw };
|
|
38
|
+
},
|
|
39
|
+
validate(props) {
|
|
40
|
+
const errors = [];
|
|
41
|
+
if (typeof props.content !== 'string' && !Array.isArray(props.content)) {
|
|
42
|
+
errors.push({ path: '/content', message: 'content must be a string or StyledRun[]' });
|
|
43
|
+
}
|
|
44
|
+
return errors;
|
|
45
|
+
},
|
|
46
|
+
measure(props, ctx) {
|
|
47
|
+
if (typeof props.content === 'string') {
|
|
48
|
+
return Promise.resolve(measurePlainText(props.content, ctx));
|
|
49
|
+
}
|
|
50
|
+
return Promise.resolve(measureRichText(props.content, ctx));
|
|
51
|
+
},
|
|
52
|
+
render(props, ctx) {
|
|
53
|
+
if (typeof props.content === 'string') {
|
|
54
|
+
renderPlainText(props.content, ctx);
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
renderRichText(props.content, ctx);
|
|
58
|
+
}
|
|
59
|
+
return Promise.resolve();
|
|
60
|
+
},
|
|
61
|
+
canSplit: true,
|
|
62
|
+
// eslint-disable-next-line @typescript-eslint/require-await
|
|
63
|
+
async split(props, ctx, availableHeight) {
|
|
64
|
+
// Only split plain text; rich text deferred to a future phase
|
|
65
|
+
if (typeof props.content !== 'string')
|
|
66
|
+
return null;
|
|
67
|
+
if (!props.content)
|
|
68
|
+
return null;
|
|
69
|
+
const style = ctx.elementStyle;
|
|
70
|
+
const font = getFont(ctx.fonts, style);
|
|
71
|
+
const fontSize = style.fontSize ?? 12;
|
|
72
|
+
const lh = getLineHeight(style);
|
|
73
|
+
const ls = style.letterSpacing ?? 0;
|
|
74
|
+
const wrapped = wrapText(props.content, font, fontSize, ctx.availableWidth, lh, undefined, ls || undefined);
|
|
75
|
+
const totalLines = wrapped.lines.length;
|
|
76
|
+
if (totalLines <= 1)
|
|
77
|
+
return null;
|
|
78
|
+
let fitLineCount = Math.floor(availableHeight / lh);
|
|
79
|
+
// Can't fit any lines
|
|
80
|
+
if (fitLineCount <= 0)
|
|
81
|
+
return null;
|
|
82
|
+
// Everything already fits
|
|
83
|
+
if (fitLineCount >= totalLines)
|
|
84
|
+
return null;
|
|
85
|
+
// Apply orphans constraint (min lines on current page)
|
|
86
|
+
const orphans = style.orphans ?? 1;
|
|
87
|
+
if (fitLineCount < orphans)
|
|
88
|
+
return null;
|
|
89
|
+
// Apply widows constraint (min lines on new page)
|
|
90
|
+
const widows = style.widows ?? 1;
|
|
91
|
+
const overflowLines = totalLines - fitLineCount;
|
|
92
|
+
if (overflowLines < widows) {
|
|
93
|
+
fitLineCount = totalLines - widows;
|
|
94
|
+
}
|
|
95
|
+
// Re-check after widows adjustment
|
|
96
|
+
if (fitLineCount <= 0 || fitLineCount >= totalLines)
|
|
97
|
+
return null;
|
|
98
|
+
if (fitLineCount < orphans)
|
|
99
|
+
return null;
|
|
100
|
+
const { fitText, overflowText } = splitWrappedText(wrapped.lines, wrapped.isLastInParagraph, fitLineCount);
|
|
101
|
+
return {
|
|
102
|
+
fit: { content: fitText, autoHeight: true },
|
|
103
|
+
overflow: { content: overflowText, autoHeight: true },
|
|
104
|
+
};
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
// ---- Plain text ----
|
|
108
|
+
function measurePlainText(text, ctx) {
|
|
109
|
+
const style = ctx.elementStyle;
|
|
110
|
+
const font = getFont(ctx.fonts, style);
|
|
111
|
+
const fontSize = style.fontSize ?? 12;
|
|
112
|
+
const lh = getLineHeight(style);
|
|
113
|
+
const ls = style.letterSpacing ?? 0;
|
|
114
|
+
const wrapOpts = { widows: style.widows, orphans: style.orphans };
|
|
115
|
+
const result = wrapText(text, font, fontSize, ctx.availableWidth, lh, wrapOpts, ls || undefined);
|
|
116
|
+
return { width: ctx.availableWidth, height: result.height };
|
|
117
|
+
}
|
|
118
|
+
function renderPlainText(text, ctx) {
|
|
119
|
+
const style = ctx.elementStyle;
|
|
120
|
+
const font = getFont(ctx.fonts, style);
|
|
121
|
+
const fontSize = style.fontSize ?? 12;
|
|
122
|
+
const lh = getLineHeight(style);
|
|
123
|
+
const color = parseColor(style.color ?? '#000000');
|
|
124
|
+
const ls = style.letterSpacing ?? 0;
|
|
125
|
+
const decoration = style.textDecoration;
|
|
126
|
+
const wrapOpts = { widows: style.widows, orphans: style.orphans };
|
|
127
|
+
const wrapped = wrapText(text, font, fontSize, ctx.width, lh, wrapOpts, ls || undefined);
|
|
128
|
+
const ascent = font.heightAtSize(fontSize, { descender: false });
|
|
129
|
+
for (let i = 0; i < wrapped.lines.length; i++) {
|
|
130
|
+
const line = wrapped.lines[i];
|
|
131
|
+
if (line === '')
|
|
132
|
+
continue;
|
|
133
|
+
const lineY = ctx.y - i * lh - ascent;
|
|
134
|
+
let lineX = ctx.x;
|
|
135
|
+
let extraWordSpacing = 0;
|
|
136
|
+
// Text alignment
|
|
137
|
+
if (style.textAlign === 'justify') {
|
|
138
|
+
// Justify: distribute extra space between words, except on last line of paragraph
|
|
139
|
+
if (!wrapped.isLastInParagraph[i] && wrapped.wordsPerLine[i] > 1) {
|
|
140
|
+
const naturalWidth = measureTextWidth(line, font, fontSize, ls || undefined);
|
|
141
|
+
const totalExtraSpace = ctx.width - naturalWidth;
|
|
142
|
+
extraWordSpacing = totalExtraSpace / (wrapped.wordsPerLine[i] - 1);
|
|
143
|
+
}
|
|
144
|
+
// Last paragraph line or single-word line: left-align
|
|
145
|
+
}
|
|
146
|
+
else if (style.textAlign === 'center' || style.textAlign === 'right') {
|
|
147
|
+
const lineWidth = measureTextWidth(line, font, fontSize, ls || undefined);
|
|
148
|
+
if (style.textAlign === 'center') {
|
|
149
|
+
lineX = ctx.x + (ctx.width - lineWidth) / 2;
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
lineX = ctx.x + ctx.width - lineWidth;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
// Determine if we need graphics state operators
|
|
156
|
+
const needsCharSpacing = ls !== 0;
|
|
157
|
+
const needsWordSpacing = extraWordSpacing > 0;
|
|
158
|
+
if (needsCharSpacing || needsWordSpacing) {
|
|
159
|
+
const ops = [pushGraphicsState()];
|
|
160
|
+
if (needsCharSpacing)
|
|
161
|
+
ops.push(setCharacterSpacing(ls));
|
|
162
|
+
if (needsWordSpacing)
|
|
163
|
+
ops.push(setWordSpacing(extraWordSpacing));
|
|
164
|
+
ctx.page.pushOperators(...ops);
|
|
165
|
+
}
|
|
166
|
+
ctx.page.drawText(line, {
|
|
167
|
+
x: lineX,
|
|
168
|
+
y: lineY,
|
|
169
|
+
font,
|
|
170
|
+
size: fontSize,
|
|
171
|
+
color: rgb(color.r, color.g, color.b),
|
|
172
|
+
opacity: ctx.opacity,
|
|
173
|
+
});
|
|
174
|
+
if (needsCharSpacing || needsWordSpacing) {
|
|
175
|
+
ctx.page.pushOperators(popGraphicsState());
|
|
176
|
+
}
|
|
177
|
+
// Text decoration — for justified lines, span the full content width
|
|
178
|
+
if (decoration && decoration !== 'none') {
|
|
179
|
+
const lineWidth = extraWordSpacing > 0 ? ctx.width : measureTextWidth(line, font, fontSize, ls || undefined);
|
|
180
|
+
drawTextDecoration(ctx.page, decoration, lineX, lineY, lineWidth, font, fontSize, color, ctx.opacity);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
// ---- Rich text (StyledRun[]) ----
|
|
185
|
+
function resolveRunStyle(run, ctx) {
|
|
186
|
+
const base = ctx.elementStyle;
|
|
187
|
+
const named = run.style ? ctx.resolveStyle(run.style) : {};
|
|
188
|
+
return { ...base, ...named, ...(run.styleOverrides ?? {}) };
|
|
189
|
+
}
|
|
190
|
+
function measureRichText(runs, ctx) {
|
|
191
|
+
let totalHeight = 0;
|
|
192
|
+
let currentLineHeight = 0;
|
|
193
|
+
let currentX = 0;
|
|
194
|
+
let lineStarted = false;
|
|
195
|
+
for (const run of runs) {
|
|
196
|
+
const style = resolveRunStyle(run, ctx);
|
|
197
|
+
const font = getFont(ctx.fonts, style);
|
|
198
|
+
const fontSize = style.fontSize ?? 12;
|
|
199
|
+
const lh = getLineHeight(style);
|
|
200
|
+
const ls = style.letterSpacing ?? 0;
|
|
201
|
+
currentLineHeight = Math.max(currentLineHeight, lh);
|
|
202
|
+
const words = run.text.split(/(\s+|\n)/);
|
|
203
|
+
for (const segment of words) {
|
|
204
|
+
if (segment === '\n') {
|
|
205
|
+
totalHeight += currentLineHeight;
|
|
206
|
+
currentX = 0;
|
|
207
|
+
currentLineHeight = lh;
|
|
208
|
+
lineStarted = false;
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
if (/^\s+$/.test(segment)) {
|
|
212
|
+
if (lineStarted) {
|
|
213
|
+
currentX += font.widthOfTextAtSize(' ', fontSize);
|
|
214
|
+
}
|
|
215
|
+
continue;
|
|
216
|
+
}
|
|
217
|
+
const segWidth = measureTextWidth(segment, font, fontSize, ls || undefined);
|
|
218
|
+
if (currentX + segWidth > ctx.availableWidth && lineStarted) {
|
|
219
|
+
totalHeight += currentLineHeight;
|
|
220
|
+
currentX = 0;
|
|
221
|
+
currentLineHeight = lh;
|
|
222
|
+
}
|
|
223
|
+
currentX += segWidth;
|
|
224
|
+
lineStarted = true;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
// Account for the last line
|
|
228
|
+
if (lineStarted || totalHeight === 0) {
|
|
229
|
+
totalHeight += currentLineHeight || getLineHeight(ctx.elementStyle);
|
|
230
|
+
}
|
|
231
|
+
return { width: ctx.availableWidth, height: totalHeight };
|
|
232
|
+
}
|
|
233
|
+
/** Add a link annotation covering a rectangular area on the page.
|
|
234
|
+
* Links starting with "#" are internal GoTo links targeting an anchor's page.
|
|
235
|
+
* All other links are external URI actions. */
|
|
236
|
+
function addLinkAnnotation(ctx, x, y, width, height, uri) {
|
|
237
|
+
const context = ctx.pdfDoc.context;
|
|
238
|
+
let actionDict;
|
|
239
|
+
if (uri.startsWith('#') && ctx.anchorPageMap) {
|
|
240
|
+
const anchorId = uri.slice(1);
|
|
241
|
+
const targetPage = ctx.anchorPageMap.get(anchorId);
|
|
242
|
+
if (!targetPage)
|
|
243
|
+
return; // anchor not found, skip link
|
|
244
|
+
actionDict = context.obj({
|
|
245
|
+
S: 'GoTo',
|
|
246
|
+
D: [targetPage.ref, PDFName.of('Fit')],
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
else {
|
|
250
|
+
actionDict = context.obj({
|
|
251
|
+
S: 'URI',
|
|
252
|
+
URI: PDFString.of(uri),
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
const annotDict = context.obj({
|
|
256
|
+
Type: 'Annot',
|
|
257
|
+
Subtype: 'Link',
|
|
258
|
+
Rect: [x, y, x + width, y + height],
|
|
259
|
+
Border: [0, 0, 0],
|
|
260
|
+
A: actionDict,
|
|
261
|
+
});
|
|
262
|
+
const annotRef = context.register(annotDict);
|
|
263
|
+
// Get or create the Annots array on the page
|
|
264
|
+
const annotsKey = PDFName.of('Annots');
|
|
265
|
+
const existing = ctx.page.node.get(annotsKey);
|
|
266
|
+
if (existing instanceof PDFArray) {
|
|
267
|
+
existing.push(annotRef);
|
|
268
|
+
}
|
|
269
|
+
else if (existing instanceof PDFRef) {
|
|
270
|
+
const resolved = context.lookup(existing);
|
|
271
|
+
if (resolved instanceof PDFArray) {
|
|
272
|
+
resolved.push(annotRef);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
else {
|
|
276
|
+
ctx.page.node.set(annotsKey, context.obj([annotRef]));
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Accumulate rich text runs into visual lines for rendering.
|
|
281
|
+
* This enables justify alignment by having complete line info before drawing.
|
|
282
|
+
*/
|
|
283
|
+
function accumulateRichLines(runs, ctx) {
|
|
284
|
+
const lines = [];
|
|
285
|
+
let currentLine = {
|
|
286
|
+
words: [],
|
|
287
|
+
totalTextWidth: 0,
|
|
288
|
+
totalSpaceWidth: 0,
|
|
289
|
+
maxLineHeight: 0,
|
|
290
|
+
spaceCount: 0,
|
|
291
|
+
isLastInParagraph: false,
|
|
292
|
+
};
|
|
293
|
+
for (const run of runs) {
|
|
294
|
+
const style = resolveRunStyle(run, ctx);
|
|
295
|
+
const font = getFont(ctx.fonts, style);
|
|
296
|
+
const fontSize = style.fontSize ?? 12;
|
|
297
|
+
const lh = getLineHeight(style);
|
|
298
|
+
const color = parseColor(style.color ?? '#000000');
|
|
299
|
+
const ascent = font.heightAtSize(fontSize, { descender: false });
|
|
300
|
+
const ls = style.letterSpacing ?? 0;
|
|
301
|
+
const spaceWidth = font.widthOfTextAtSize(' ', fontSize);
|
|
302
|
+
const segments = run.text.split(/(\s+|\n)/);
|
|
303
|
+
let wordsBeforeRun = currentLine.words.length;
|
|
304
|
+
for (const segment of segments) {
|
|
305
|
+
if (segment === '\n') {
|
|
306
|
+
// Explicit newline — finalize current line as last-in-paragraph
|
|
307
|
+
currentLine.isLastInParagraph = true;
|
|
308
|
+
if (currentLine.words.length > 0 || lines.length === 0) {
|
|
309
|
+
lines.push(currentLine);
|
|
310
|
+
}
|
|
311
|
+
currentLine = {
|
|
312
|
+
words: [],
|
|
313
|
+
totalTextWidth: 0,
|
|
314
|
+
totalSpaceWidth: 0,
|
|
315
|
+
maxLineHeight: 0,
|
|
316
|
+
spaceCount: 0,
|
|
317
|
+
isLastInParagraph: false,
|
|
318
|
+
};
|
|
319
|
+
wordsBeforeRun = 0;
|
|
320
|
+
continue;
|
|
321
|
+
}
|
|
322
|
+
if (/^\s+$/.test(segment)) {
|
|
323
|
+
if (currentLine.words.length > 0) {
|
|
324
|
+
currentLine.totalSpaceWidth += spaceWidth;
|
|
325
|
+
currentLine.spaceCount++;
|
|
326
|
+
}
|
|
327
|
+
continue;
|
|
328
|
+
}
|
|
329
|
+
const segWidth = measureTextWidth(segment, font, fontSize, ls || undefined);
|
|
330
|
+
const lineWidthWithWord = currentLine.totalTextWidth + currentLine.totalSpaceWidth + segWidth;
|
|
331
|
+
if (lineWidthWithWord > ctx.width && currentLine.words.length > 0) {
|
|
332
|
+
// Overflow — push current line, start new one
|
|
333
|
+
lines.push(currentLine);
|
|
334
|
+
currentLine = {
|
|
335
|
+
words: [],
|
|
336
|
+
totalTextWidth: 0,
|
|
337
|
+
totalSpaceWidth: 0,
|
|
338
|
+
maxLineHeight: 0,
|
|
339
|
+
spaceCount: 0,
|
|
340
|
+
isLastInParagraph: false,
|
|
341
|
+
};
|
|
342
|
+
wordsBeforeRun = 0;
|
|
343
|
+
}
|
|
344
|
+
currentLine.words.push({
|
|
345
|
+
text: segment,
|
|
346
|
+
font,
|
|
347
|
+
fontSize,
|
|
348
|
+
color,
|
|
349
|
+
ascent,
|
|
350
|
+
lh,
|
|
351
|
+
width: segWidth,
|
|
352
|
+
letterSpacing: ls,
|
|
353
|
+
decoration: style.textDecoration,
|
|
354
|
+
link: run.link,
|
|
355
|
+
opacity: ctx.opacity,
|
|
356
|
+
});
|
|
357
|
+
currentLine.totalTextWidth += segWidth;
|
|
358
|
+
currentLine.maxLineHeight = Math.max(currentLine.maxLineHeight, lh);
|
|
359
|
+
}
|
|
360
|
+
// Register footnote marker on the last word of this run
|
|
361
|
+
if (run.footnote && ctx.footnoteMarker && currentLine.words.length > wordsBeforeRun) {
|
|
362
|
+
const fnNumber = ctx.footnoteMarker(run.footnote);
|
|
363
|
+
const lastWord = currentLine.words[currentLine.words.length - 1];
|
|
364
|
+
lastWord.footnoteNumber = fnNumber;
|
|
365
|
+
// Track superscript width separately so it doesn't inflate word.width for decorations
|
|
366
|
+
const superFontSize = fontSize * 0.65;
|
|
367
|
+
const numWidth = font.widthOfTextAtSize(String(fnNumber), superFontSize);
|
|
368
|
+
lastWord.footnoteWidth = numWidth;
|
|
369
|
+
currentLine.totalTextWidth += numWidth;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
// Push the last line (always last in paragraph)
|
|
373
|
+
if (currentLine.words.length > 0) {
|
|
374
|
+
currentLine.isLastInParagraph = true;
|
|
375
|
+
lines.push(currentLine);
|
|
376
|
+
}
|
|
377
|
+
return lines;
|
|
378
|
+
}
|
|
379
|
+
function renderRichText(runs, ctx) {
|
|
380
|
+
const textAlign = ctx.elementStyle.textAlign;
|
|
381
|
+
const richLines = accumulateRichLines(runs, ctx);
|
|
382
|
+
let currentY = ctx.y;
|
|
383
|
+
for (let lineIdx = 0; lineIdx < richLines.length; lineIdx++) {
|
|
384
|
+
const line = richLines[lineIdx];
|
|
385
|
+
if (line.words.length === 0) {
|
|
386
|
+
currentY -= line.maxLineHeight || getLineHeight(ctx.elementStyle);
|
|
387
|
+
continue;
|
|
388
|
+
}
|
|
389
|
+
const naturalWidth = line.totalTextWidth + line.totalSpaceWidth;
|
|
390
|
+
let currentX = ctx.x;
|
|
391
|
+
let extraWordGap = 0;
|
|
392
|
+
if (textAlign === 'justify' &&
|
|
393
|
+
!line.isLastInParagraph &&
|
|
394
|
+
line.words.length > 1 &&
|
|
395
|
+
line.spaceCount > 0) {
|
|
396
|
+
const extraSpace = ctx.width - naturalWidth;
|
|
397
|
+
extraWordGap = extraSpace / line.spaceCount;
|
|
398
|
+
}
|
|
399
|
+
else if (textAlign === 'center') {
|
|
400
|
+
currentX = ctx.x + (ctx.width - naturalWidth) / 2;
|
|
401
|
+
}
|
|
402
|
+
else if (textAlign === 'right') {
|
|
403
|
+
currentX = ctx.x + ctx.width - naturalWidth;
|
|
404
|
+
}
|
|
405
|
+
let activeSpan = null;
|
|
406
|
+
const decorationSpans = [];
|
|
407
|
+
// Render each word in the line
|
|
408
|
+
for (let wIdx = 0; wIdx < line.words.length; wIdx++) {
|
|
409
|
+
const word = line.words[wIdx];
|
|
410
|
+
const drawY = currentY - word.ascent;
|
|
411
|
+
// Set character spacing if needed
|
|
412
|
+
const needsCharSpacing = word.letterSpacing !== 0;
|
|
413
|
+
if (needsCharSpacing) {
|
|
414
|
+
ctx.page.pushOperators(pushGraphicsState(), setCharacterSpacing(word.letterSpacing));
|
|
415
|
+
}
|
|
416
|
+
ctx.page.drawText(word.text, {
|
|
417
|
+
x: currentX,
|
|
418
|
+
y: drawY,
|
|
419
|
+
font: word.font,
|
|
420
|
+
size: word.fontSize,
|
|
421
|
+
color: rgb(word.color.r, word.color.g, word.color.b),
|
|
422
|
+
opacity: word.opacity,
|
|
423
|
+
});
|
|
424
|
+
if (needsCharSpacing) {
|
|
425
|
+
ctx.page.pushOperators(popGraphicsState());
|
|
426
|
+
}
|
|
427
|
+
// Render footnote superscript number after the word text
|
|
428
|
+
if (word.footnoteNumber !== undefined) {
|
|
429
|
+
const numText = String(word.footnoteNumber);
|
|
430
|
+
const superFontSize = word.fontSize * 0.65;
|
|
431
|
+
const superAscent = word.font.heightAtSize(superFontSize, { descender: false });
|
|
432
|
+
const superRaise = word.ascent * 0.35;
|
|
433
|
+
// Superscript starts right after the word text
|
|
434
|
+
const superX = currentX + word.width;
|
|
435
|
+
ctx.page.drawText(numText, {
|
|
436
|
+
x: superX,
|
|
437
|
+
y: drawY + superRaise + (word.ascent - superAscent),
|
|
438
|
+
font: word.font,
|
|
439
|
+
size: superFontSize,
|
|
440
|
+
color: rgb(word.color.r, word.color.g, word.color.b),
|
|
441
|
+
opacity: word.opacity,
|
|
442
|
+
});
|
|
443
|
+
}
|
|
444
|
+
// Accumulate decoration spans — extend or start new
|
|
445
|
+
const wordDecoration = word.decoration && word.decoration !== 'none' ? word.decoration : null;
|
|
446
|
+
if (wordDecoration) {
|
|
447
|
+
if (activeSpan && activeSpan.decoration === wordDecoration) {
|
|
448
|
+
// Extend the current span through the space gap to this word's end
|
|
449
|
+
activeSpan.endX = currentX + word.width;
|
|
450
|
+
}
|
|
451
|
+
else {
|
|
452
|
+
// Finalize previous span and start new one
|
|
453
|
+
if (activeSpan)
|
|
454
|
+
decorationSpans.push(activeSpan);
|
|
455
|
+
activeSpan = {
|
|
456
|
+
decoration: wordDecoration,
|
|
457
|
+
startX: currentX,
|
|
458
|
+
endX: currentX + word.width,
|
|
459
|
+
font: word.font,
|
|
460
|
+
fontSize: word.fontSize,
|
|
461
|
+
color: word.color,
|
|
462
|
+
drawY,
|
|
463
|
+
opacity: word.opacity,
|
|
464
|
+
};
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
else {
|
|
468
|
+
// No decoration — finalize any active span
|
|
469
|
+
if (activeSpan) {
|
|
470
|
+
decorationSpans.push(activeSpan);
|
|
471
|
+
activeSpan = null;
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
// Link annotation
|
|
475
|
+
if (word.link) {
|
|
476
|
+
addLinkAnnotation(ctx, currentX, currentY - line.maxLineHeight, word.width + (word.footnoteWidth ?? 0), line.maxLineHeight, word.link);
|
|
477
|
+
}
|
|
478
|
+
currentX += word.width + (word.footnoteWidth ?? 0);
|
|
479
|
+
// Add space after this word (with justify gap if applicable)
|
|
480
|
+
// Use current word's font for space width to match measurement in accumulateRichLines
|
|
481
|
+
if (wIdx < line.words.length - 1) {
|
|
482
|
+
const baseSpace = word.font.widthOfTextAtSize(' ', word.fontSize);
|
|
483
|
+
currentX += baseSpace + extraWordGap;
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
// Finalize last span
|
|
487
|
+
if (activeSpan)
|
|
488
|
+
decorationSpans.push(activeSpan);
|
|
489
|
+
// Draw all decoration spans as continuous lines
|
|
490
|
+
for (const span of decorationSpans) {
|
|
491
|
+
drawTextDecoration(ctx.page, span.decoration, span.startX, span.drawY, span.endX - span.startX, span.font, span.fontSize, span.color, span.opacity);
|
|
492
|
+
}
|
|
493
|
+
currentY -= line.maxLineHeight;
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
//# sourceMappingURL=text-plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text-plugin.js","sourceRoot":"","sources":["../../src/text/text-plugin.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { PDFFont } from 'pdf-lib';
|
|
2
|
+
export interface WrapResult {
|
|
3
|
+
/** Wrapped lines of text. */
|
|
4
|
+
lines: string[];
|
|
5
|
+
/** Total height of all lines. */
|
|
6
|
+
height: number;
|
|
7
|
+
/** Number of words per line (parallel to lines). */
|
|
8
|
+
wordsPerLine: number[];
|
|
9
|
+
/** Whether each line is the last in its paragraph (parallel to lines). */
|
|
10
|
+
isLastInParagraph: boolean[];
|
|
11
|
+
}
|
|
12
|
+
/** Options for widow/orphan control. */
|
|
13
|
+
export interface WrapOptions {
|
|
14
|
+
/** Minimum lines at the bottom of a column/page (before a break). */
|
|
15
|
+
orphans?: number;
|
|
16
|
+
/** Minimum lines at the top of a column/page (after a break). */
|
|
17
|
+
widows?: number;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Wrap text to fit within a given width.
|
|
21
|
+
*
|
|
22
|
+
* Splits on explicit newlines first, then wraps each paragraph.
|
|
23
|
+
* Words longer than maxWidth are broken at character level.
|
|
24
|
+
*/
|
|
25
|
+
export declare function wrapText(text: string, font: PDFFont, fontSize: number, maxWidth: number, lineHeight: number, _options?: WrapOptions, letterSpacing?: number): WrapResult;
|
|
26
|
+
/**
|
|
27
|
+
* Split wrapped lines into two text strings at a given line index.
|
|
28
|
+
* Preserves paragraph boundaries (newlines) based on `isLastInParagraph` metadata.
|
|
29
|
+
*
|
|
30
|
+
* @param lines - Wrapped lines from `wrapText()`.
|
|
31
|
+
* @param isLastInParagraph - Parallel array indicating paragraph endings.
|
|
32
|
+
* @param splitIndex - Line index at which to split (lines 0..splitIndex-1 go to fit).
|
|
33
|
+
* @returns Two text strings: fit (before split) and overflow (after split).
|
|
34
|
+
*/
|
|
35
|
+
export declare function splitWrappedText(lines: string[], isLastInParagraph: boolean[], splitIndex: number): {
|
|
36
|
+
fitText: string;
|
|
37
|
+
overflowText: string;
|
|
38
|
+
};
|
|
39
|
+
/** Measure the width of a text string, accounting for optional letter spacing. */
|
|
40
|
+
export declare function measureTextWidth(text: string, font: PDFFont, fontSize: number, letterSpacing?: number): number;
|
|
41
|
+
//# sourceMappingURL=word-wrap.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"word-wrap.d.ts","sourceRoot":"","sources":["../../src/text/word-wrap.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAEvC,MAAM,WAAW,UAAU;IACzB,6BAA6B;IAC7B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,iCAAiC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,oDAAoD;IACpD,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,0EAA0E;IAC1E,iBAAiB,EAAE,OAAO,EAAE,CAAC;CAC9B;AAED,wCAAwC;AACxC,MAAM,WAAW,WAAW;IAC1B,qEAAqE;IACrE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iEAAiE;IACjE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CACtB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,OAAO,EACb,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,QAAQ,CAAC,EAAE,WAAW,EACtB,aAAa,CAAC,EAAE,MAAM,GACrB,UAAU,CAmGZ;AAgCD;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,MAAM,EAAE,EACf,iBAAiB,EAAE,OAAO,EAAE,EAC5B,UAAU,EAAE,MAAM,GACjB;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,CAK3C;AAsBD,kFAAkF;AAClF,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,OAAO,EACb,QAAQ,EAAE,MAAM,EAChB,aAAa,CAAC,EAAE,MAAM,GACrB,MAAM,CAMR"}
|