react-pdf-highlighter-plus 1.0.0
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 +22 -0
- package/README.md +411 -0
- package/dist/esm/components/AreaHighlight.d.ts +82 -0
- package/dist/esm/components/AreaHighlight.js +109 -0
- package/dist/esm/components/AreaHighlight.js.map +1 -0
- package/dist/esm/components/DrawingCanvas.d.ts +48 -0
- package/dist/esm/components/DrawingCanvas.js +277 -0
- package/dist/esm/components/DrawingCanvas.js.map +1 -0
- package/dist/esm/components/DrawingHighlight.d.ts +70 -0
- package/dist/esm/components/DrawingHighlight.js +164 -0
- package/dist/esm/components/DrawingHighlight.js.map +1 -0
- package/dist/esm/components/FreetextHighlight.d.ts +112 -0
- package/dist/esm/components/FreetextHighlight.js +193 -0
- package/dist/esm/components/FreetextHighlight.js.map +1 -0
- package/dist/esm/components/HighlightLayer.d.ts +49 -0
- package/dist/esm/components/HighlightLayer.js +37 -0
- package/dist/esm/components/HighlightLayer.js.map +1 -0
- package/dist/esm/components/ImageHighlight.d.ts +63 -0
- package/dist/esm/components/ImageHighlight.js +65 -0
- package/dist/esm/components/ImageHighlight.js.map +1 -0
- package/dist/esm/components/MonitoredHighlightContainer.d.ts +37 -0
- package/dist/esm/components/MonitoredHighlightContainer.js +42 -0
- package/dist/esm/components/MonitoredHighlightContainer.js.map +1 -0
- package/dist/esm/components/MouseMonitor.d.ts +34 -0
- package/dist/esm/components/MouseMonitor.js +30 -0
- package/dist/esm/components/MouseMonitor.js.map +1 -0
- package/dist/esm/components/MouseSelection.d.ts +66 -0
- package/dist/esm/components/MouseSelection.js +122 -0
- package/dist/esm/components/MouseSelection.js.map +1 -0
- package/dist/esm/components/PdfHighlighter.d.ts +184 -0
- package/dist/esm/components/PdfHighlighter.js +410 -0
- package/dist/esm/components/PdfHighlighter.js.map +1 -0
- package/dist/esm/components/PdfLoader.d.ts +55 -0
- package/dist/esm/components/PdfLoader.js +57 -0
- package/dist/esm/components/PdfLoader.js.map +1 -0
- package/dist/esm/components/ShapeCanvas.d.ts +51 -0
- package/dist/esm/components/ShapeCanvas.js +205 -0
- package/dist/esm/components/ShapeCanvas.js.map +1 -0
- package/dist/esm/components/ShapeHighlight.d.ts +107 -0
- package/dist/esm/components/ShapeHighlight.js +140 -0
- package/dist/esm/components/ShapeHighlight.js.map +1 -0
- package/dist/esm/components/SignaturePad.d.ts +40 -0
- package/dist/esm/components/SignaturePad.js +138 -0
- package/dist/esm/components/SignaturePad.js.map +1 -0
- package/dist/esm/components/TextHighlight.d.ts +93 -0
- package/dist/esm/components/TextHighlight.js +115 -0
- package/dist/esm/components/TextHighlight.js.map +1 -0
- package/dist/esm/components/TipContainer.d.ts +27 -0
- package/dist/esm/components/TipContainer.js +58 -0
- package/dist/esm/components/TipContainer.js.map +1 -0
- package/dist/esm/contexts/HighlightContext.d.ts +44 -0
- package/dist/esm/contexts/HighlightContext.js +16 -0
- package/dist/esm/contexts/HighlightContext.js.map +1 -0
- package/dist/esm/contexts/PdfHighlighterContext.d.ts +89 -0
- package/dist/esm/contexts/PdfHighlighterContext.js +16 -0
- package/dist/esm/contexts/PdfHighlighterContext.js.map +1 -0
- package/dist/esm/index.d.ts +19 -0
- package/dist/esm/index.js +19 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/lib/coordinates.d.ts +16 -0
- package/dist/esm/lib/coordinates.js +69 -0
- package/dist/esm/lib/coordinates.js.map +1 -0
- package/dist/esm/lib/export-pdf.d.ts +81 -0
- package/dist/esm/lib/export-pdf.js +511 -0
- package/dist/esm/lib/export-pdf.js.map +1 -0
- package/dist/esm/lib/get-bounding-rect.d.ts +3 -0
- package/dist/esm/lib/get-bounding-rect.js +35 -0
- package/dist/esm/lib/get-bounding-rect.js.map +1 -0
- package/dist/esm/lib/get-client-rects.d.ts +3 -0
- package/dist/esm/lib/get-client-rects.js +43 -0
- package/dist/esm/lib/get-client-rects.js.map +1 -0
- package/dist/esm/lib/group-highlights-by-page.d.ts +6 -0
- package/dist/esm/lib/group-highlights-by-page.js +23 -0
- package/dist/esm/lib/group-highlights-by-page.js.map +1 -0
- package/dist/esm/lib/optimize-client-rects.d.ts +3 -0
- package/dist/esm/lib/optimize-client-rects.js +65 -0
- package/dist/esm/lib/optimize-client-rects.js.map +1 -0
- package/dist/esm/lib/pdfjs-dom.d.ts +9 -0
- package/dist/esm/lib/pdfjs-dom.js +55 -0
- package/dist/esm/lib/pdfjs-dom.js.map +1 -0
- package/dist/esm/lib/screenshot.d.ts +4 -0
- package/dist/esm/lib/screenshot.js +24 -0
- package/dist/esm/lib/screenshot.js.map +1 -0
- package/dist/esm/style/AreaHighlight.css +134 -0
- package/dist/esm/style/DrawingCanvas.css +62 -0
- package/dist/esm/style/DrawingHighlight.css +184 -0
- package/dist/esm/style/FreetextHighlight.css +249 -0
- package/dist/esm/style/ImageHighlight.css +97 -0
- package/dist/esm/style/MouseSelection.css +15 -0
- package/dist/esm/style/PdfHighlighter.css +77 -0
- package/dist/esm/style/ShapeCanvas.css +47 -0
- package/dist/esm/style/ShapeHighlight.css +182 -0
- package/dist/esm/style/SignaturePad.css +83 -0
- package/dist/esm/style/TextHighlight.css +199 -0
- package/dist/esm/style/pdf_viewer.css +41 -0
- package/dist/esm/types.d.ts +213 -0
- package/dist/esm/types.js +2 -0
- package/dist/esm/types.js.map +1 -0
- package/package.json +91 -0
|
@@ -0,0 +1,511 @@
|
|
|
1
|
+
import { PDFDocument, rgb, StandardFonts } from "pdf-lib";
|
|
2
|
+
/**
|
|
3
|
+
* Parse a color string to RGB values (0-1 range).
|
|
4
|
+
*/
|
|
5
|
+
function parseColor(color) {
|
|
6
|
+
// Handle rgba(r, g, b, a) and rgb(r, g, b)
|
|
7
|
+
const rgbaMatch = color.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)/);
|
|
8
|
+
if (rgbaMatch) {
|
|
9
|
+
return {
|
|
10
|
+
r: parseInt(rgbaMatch[1]) / 255,
|
|
11
|
+
g: parseInt(rgbaMatch[2]) / 255,
|
|
12
|
+
b: parseInt(rgbaMatch[3]) / 255,
|
|
13
|
+
a: rgbaMatch[4] ? parseFloat(rgbaMatch[4]) : 1,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
// Handle hex (#RRGGBB or #RGB)
|
|
17
|
+
const hex = color.replace("#", "");
|
|
18
|
+
if (hex.length === 3) {
|
|
19
|
+
return {
|
|
20
|
+
r: parseInt(hex[0] + hex[0], 16) / 255,
|
|
21
|
+
g: parseInt(hex[1] + hex[1], 16) / 255,
|
|
22
|
+
b: parseInt(hex[2] + hex[2], 16) / 255,
|
|
23
|
+
a: 1,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
if (hex.length === 6) {
|
|
27
|
+
return {
|
|
28
|
+
r: parseInt(hex.slice(0, 2), 16) / 255,
|
|
29
|
+
g: parseInt(hex.slice(2, 4), 16) / 255,
|
|
30
|
+
b: parseInt(hex.slice(4, 6), 16) / 255,
|
|
31
|
+
a: 1,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
// Default yellow
|
|
35
|
+
return { r: 1, g: 0.89, b: 0.56, a: 0.5 };
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Convert ScaledPosition coordinates to PDF points.
|
|
39
|
+
* PDF coordinate system has origin at bottom-left.
|
|
40
|
+
*/
|
|
41
|
+
function scaledToPdfPoints(scaled, page) {
|
|
42
|
+
const pdfWidth = page.getWidth();
|
|
43
|
+
const pdfHeight = page.getHeight();
|
|
44
|
+
// Calculate position ratios
|
|
45
|
+
const xRatio = pdfWidth / scaled.width;
|
|
46
|
+
const yRatio = pdfHeight / scaled.height;
|
|
47
|
+
const x = scaled.x1 * xRatio;
|
|
48
|
+
const width = (scaled.x2 - scaled.x1) * xRatio;
|
|
49
|
+
const height = (scaled.y2 - scaled.y1) * yRatio;
|
|
50
|
+
// Flip Y (PDF origin is bottom-left, screen origin is top-left)
|
|
51
|
+
const y = pdfHeight - scaled.y1 * yRatio - height;
|
|
52
|
+
return { x, y, width, height };
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Convert base64 data URL to bytes.
|
|
56
|
+
*/
|
|
57
|
+
function dataUrlToBytes(dataUrl) {
|
|
58
|
+
const base64 = dataUrl.split(",")[1];
|
|
59
|
+
const byteString = atob(base64);
|
|
60
|
+
const bytes = new Uint8Array(byteString.length);
|
|
61
|
+
for (let i = 0; i < byteString.length; i++) {
|
|
62
|
+
bytes[i] = byteString.charCodeAt(i);
|
|
63
|
+
}
|
|
64
|
+
const type = dataUrl.includes("image/png") ? "png" : "jpg";
|
|
65
|
+
return { bytes, type };
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Wrap text into multiple lines that fit within maxWidth.
|
|
69
|
+
* Long words are broken character by character (like CSS word-wrap: break-word).
|
|
70
|
+
*/
|
|
71
|
+
function wrapText(text, font, fontSize, maxWidth) {
|
|
72
|
+
if (!text || maxWidth <= 0)
|
|
73
|
+
return [];
|
|
74
|
+
const lines = [];
|
|
75
|
+
// Split by newlines first to preserve intentional line breaks
|
|
76
|
+
const paragraphs = text.split(/\n/);
|
|
77
|
+
for (const paragraph of paragraphs) {
|
|
78
|
+
if (!paragraph.trim()) {
|
|
79
|
+
lines.push("");
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
const words = paragraph.split(/\s+/);
|
|
83
|
+
let currentLine = "";
|
|
84
|
+
for (const word of words) {
|
|
85
|
+
const testLine = currentLine ? `${currentLine} ${word}` : word;
|
|
86
|
+
const testWidth = font.widthOfTextAtSize(testLine, fontSize);
|
|
87
|
+
if (testWidth <= maxWidth) {
|
|
88
|
+
currentLine = testLine;
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
// Push current line if exists
|
|
92
|
+
if (currentLine) {
|
|
93
|
+
lines.push(currentLine);
|
|
94
|
+
currentLine = "";
|
|
95
|
+
}
|
|
96
|
+
// Check if word itself is too wide - break it character by character
|
|
97
|
+
if (font.widthOfTextAtSize(word, fontSize) > maxWidth) {
|
|
98
|
+
let remaining = word;
|
|
99
|
+
while (remaining.length > 0) {
|
|
100
|
+
let charCount = 1;
|
|
101
|
+
// Find how many characters fit in maxWidth
|
|
102
|
+
while (charCount < remaining.length &&
|
|
103
|
+
font.widthOfTextAtSize(remaining.substring(0, charCount + 1), fontSize) <= maxWidth) {
|
|
104
|
+
charCount++;
|
|
105
|
+
}
|
|
106
|
+
const chunk = remaining.substring(0, charCount);
|
|
107
|
+
remaining = remaining.substring(charCount);
|
|
108
|
+
if (remaining.length > 0) {
|
|
109
|
+
// More characters remaining, push this chunk as a complete line
|
|
110
|
+
lines.push(chunk);
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
// Last chunk, keep it as current line (may combine with next word)
|
|
114
|
+
currentLine = chunk;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
currentLine = word;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
if (currentLine)
|
|
124
|
+
lines.push(currentLine);
|
|
125
|
+
}
|
|
126
|
+
return lines;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Group highlights by page number.
|
|
130
|
+
*/
|
|
131
|
+
function groupByPage(highlights) {
|
|
132
|
+
const map = new Map();
|
|
133
|
+
for (const h of highlights) {
|
|
134
|
+
const pageNum = h.position.boundingRect.pageNumber;
|
|
135
|
+
if (!map.has(pageNum))
|
|
136
|
+
map.set(pageNum, []);
|
|
137
|
+
map.get(pageNum).push(h);
|
|
138
|
+
}
|
|
139
|
+
return map;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Render a text highlight (multiple rectangles for multi-line selections).
|
|
143
|
+
* Supports highlight (background), underline, and strikethrough styles.
|
|
144
|
+
*/
|
|
145
|
+
async function renderTextHighlight(page, highlight, options) {
|
|
146
|
+
// Per-highlight color override or fallback to default
|
|
147
|
+
const colorStr = highlight.highlightColor ||
|
|
148
|
+
options.textHighlightColor ||
|
|
149
|
+
"rgba(255, 226, 143, 0.5)";
|
|
150
|
+
const color = parseColor(colorStr);
|
|
151
|
+
const highlightStyle = highlight.highlightStyle || "highlight";
|
|
152
|
+
// Text highlights use rects array for multi-line selections
|
|
153
|
+
const rects = highlight.position.rects.length > 0
|
|
154
|
+
? highlight.position.rects
|
|
155
|
+
: [highlight.position.boundingRect];
|
|
156
|
+
for (const rect of rects) {
|
|
157
|
+
const { x, y, width, height } = scaledToPdfPoints(rect, page);
|
|
158
|
+
if (highlightStyle === "highlight") {
|
|
159
|
+
// Draw filled rectangle for background highlight
|
|
160
|
+
page.drawRectangle({
|
|
161
|
+
x,
|
|
162
|
+
y,
|
|
163
|
+
width,
|
|
164
|
+
height,
|
|
165
|
+
color: rgb(color.r, color.g, color.b),
|
|
166
|
+
opacity: color.a,
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
else if (highlightStyle === "underline") {
|
|
170
|
+
// Draw line at bottom of rectangle
|
|
171
|
+
const lineThickness = Math.max(1, height * 0.1);
|
|
172
|
+
page.drawRectangle({
|
|
173
|
+
x,
|
|
174
|
+
y,
|
|
175
|
+
width,
|
|
176
|
+
height: lineThickness,
|
|
177
|
+
color: rgb(color.r, color.g, color.b),
|
|
178
|
+
opacity: color.a,
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
else if (highlightStyle === "strikethrough") {
|
|
182
|
+
// Draw line through middle of rectangle
|
|
183
|
+
const lineThickness = Math.max(1, height * 0.1);
|
|
184
|
+
const lineY = y + height / 2 - lineThickness / 2;
|
|
185
|
+
page.drawRectangle({
|
|
186
|
+
x,
|
|
187
|
+
y: lineY,
|
|
188
|
+
width,
|
|
189
|
+
height: lineThickness,
|
|
190
|
+
color: rgb(color.r, color.g, color.b),
|
|
191
|
+
opacity: color.a,
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Render an area highlight (single rectangle).
|
|
198
|
+
*/
|
|
199
|
+
async function renderAreaHighlight(page, highlight, options) {
|
|
200
|
+
// Per-highlight color override or fallback to default
|
|
201
|
+
const colorStr = highlight.highlightColor ||
|
|
202
|
+
options.areaHighlightColor ||
|
|
203
|
+
"rgba(255, 226, 143, 0.5)";
|
|
204
|
+
const color = parseColor(colorStr);
|
|
205
|
+
const { x, y, width, height } = scaledToPdfPoints(highlight.position.boundingRect, page);
|
|
206
|
+
page.drawRectangle({
|
|
207
|
+
x,
|
|
208
|
+
y,
|
|
209
|
+
width,
|
|
210
|
+
height,
|
|
211
|
+
color: rgb(color.r, color.g, color.b),
|
|
212
|
+
opacity: color.a,
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Render a freetext highlight (background rectangle + text).
|
|
217
|
+
* Text is wrapped to fit within the box.
|
|
218
|
+
*/
|
|
219
|
+
async function renderFreetextHighlight(page, highlight, options, font) {
|
|
220
|
+
const text = highlight.content?.text || "";
|
|
221
|
+
const textColor = parseColor(highlight.color || options.defaultFreetextColor || "#333333");
|
|
222
|
+
// Get box dimensions in PDF points
|
|
223
|
+
const { x, y, width, height } = scaledToPdfPoints(highlight.position.boundingRect, page);
|
|
224
|
+
// Scale font size by the same ratio used for the box coordinates
|
|
225
|
+
// This ensures the font scales proportionally with the box
|
|
226
|
+
const pdfHeight = page.getHeight();
|
|
227
|
+
const yRatio = pdfHeight / highlight.position.boundingRect.height;
|
|
228
|
+
const storedFontSize = parseInt(highlight.fontSize || "") || options.defaultFreetextFontSize || 14;
|
|
229
|
+
const fontSize = storedFontSize * yRatio;
|
|
230
|
+
console.log("Freetext export:", {
|
|
231
|
+
storedFontSize,
|
|
232
|
+
yRatio,
|
|
233
|
+
fontSize,
|
|
234
|
+
boxDimensions: { x, y, width, height },
|
|
235
|
+
text: text.substring(0, 50),
|
|
236
|
+
});
|
|
237
|
+
// Draw background (skip if transparent)
|
|
238
|
+
const bgColorValue = highlight.backgroundColor || options.defaultFreetextBgColor || "#ffffc8";
|
|
239
|
+
if (bgColorValue !== "transparent") {
|
|
240
|
+
const bgColor = parseColor(bgColorValue);
|
|
241
|
+
page.drawRectangle({
|
|
242
|
+
x,
|
|
243
|
+
y,
|
|
244
|
+
width,
|
|
245
|
+
height,
|
|
246
|
+
color: rgb(bgColor.r, bgColor.g, bgColor.b),
|
|
247
|
+
opacity: bgColor.a,
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
// Draw wrapped text with scaled padding
|
|
251
|
+
const padding = 4 * yRatio;
|
|
252
|
+
const maxWidth = width - padding * 2;
|
|
253
|
+
const lineHeight = fontSize * 1.3;
|
|
254
|
+
if (maxWidth > 0 && text) {
|
|
255
|
+
const lines = wrapText(text, font, fontSize, maxWidth);
|
|
256
|
+
let currentY = y + height - fontSize - padding;
|
|
257
|
+
for (const line of lines) {
|
|
258
|
+
// Stop if we've run out of vertical space
|
|
259
|
+
if (currentY < y + padding)
|
|
260
|
+
break;
|
|
261
|
+
// Skip empty lines but still move down
|
|
262
|
+
if (line.trim()) {
|
|
263
|
+
page.drawText(line, {
|
|
264
|
+
x: x + padding,
|
|
265
|
+
y: currentY,
|
|
266
|
+
size: fontSize,
|
|
267
|
+
font,
|
|
268
|
+
color: rgb(textColor.r, textColor.g, textColor.b),
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
currentY -= lineHeight;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Transform visual coordinates to raw MediaBox coordinates.
|
|
277
|
+
* pdf-lib's drawImage uses raw MediaBox space, but our coordinates are in visual space.
|
|
278
|
+
*/
|
|
279
|
+
function transformToRawCoordinates(page, x, y, width, height) {
|
|
280
|
+
const rotation = page.getRotation().angle;
|
|
281
|
+
const pageWidth = page.getWidth(); // Visual width
|
|
282
|
+
const pageHeight = page.getHeight(); // Visual height
|
|
283
|
+
if (rotation === 90) {
|
|
284
|
+
// Visual (x, y) → Raw MediaBox coordinates
|
|
285
|
+
// When rotated 90° CCW, visual top-left maps to raw bottom-left
|
|
286
|
+
return {
|
|
287
|
+
x: y,
|
|
288
|
+
y: pageWidth - x - width,
|
|
289
|
+
width: height,
|
|
290
|
+
height: width,
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
else if (rotation === 180) {
|
|
294
|
+
// Rotated 180°, origin flips to opposite corner
|
|
295
|
+
return {
|
|
296
|
+
x: pageWidth - x - width,
|
|
297
|
+
y: pageHeight - y - height,
|
|
298
|
+
width,
|
|
299
|
+
height,
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
else if (rotation === 270) {
|
|
303
|
+
// When rotated 90° CW (270° CCW)
|
|
304
|
+
return {
|
|
305
|
+
x: pageHeight - y - height,
|
|
306
|
+
y: x,
|
|
307
|
+
width: height,
|
|
308
|
+
height: width,
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
// No rotation - coordinates are already correct
|
|
312
|
+
return { x, y, width, height };
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Render an image highlight (embedded image).
|
|
316
|
+
* Handles page rotation by transforming visual coordinates to raw MediaBox space.
|
|
317
|
+
* Image fills the entire bounding box to match the visual wrapper in preview.
|
|
318
|
+
*/
|
|
319
|
+
async function renderImageHighlight(pdfDoc, page, highlight) {
|
|
320
|
+
const imageDataUrl = highlight.content?.image;
|
|
321
|
+
if (!imageDataUrl)
|
|
322
|
+
return;
|
|
323
|
+
try {
|
|
324
|
+
const { bytes, type } = dataUrlToBytes(imageDataUrl);
|
|
325
|
+
const image = type === "png"
|
|
326
|
+
? await pdfDoc.embedPng(bytes)
|
|
327
|
+
: await pdfDoc.embedJpg(bytes);
|
|
328
|
+
// Calculate coordinates in visual space - use full bounding box dimensions
|
|
329
|
+
const visualCoords = scaledToPdfPoints(highlight.position.boundingRect, page);
|
|
330
|
+
// Transform to raw MediaBox coordinates based on page rotation
|
|
331
|
+
const rawCoords = transformToRawCoordinates(page, visualCoords.x, visualCoords.y, visualCoords.width, visualCoords.height);
|
|
332
|
+
console.log("Image export:", {
|
|
333
|
+
rotation: page.getRotation().angle,
|
|
334
|
+
visualCoords,
|
|
335
|
+
rawCoords,
|
|
336
|
+
});
|
|
337
|
+
// Draw image filling the entire bounding box
|
|
338
|
+
page.drawImage(image, {
|
|
339
|
+
x: rawCoords.x,
|
|
340
|
+
y: rawCoords.y,
|
|
341
|
+
width: rawCoords.width,
|
|
342
|
+
height: rawCoords.height,
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
catch (error) {
|
|
346
|
+
console.error("Failed to embed image:", error);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Render a shape highlight (rectangle, circle, or arrow).
|
|
351
|
+
*/
|
|
352
|
+
async function renderShapeHighlight(page, highlight) {
|
|
353
|
+
// Get shape data from content or top-level properties
|
|
354
|
+
const shapeType = highlight.content?.shape?.shapeType || highlight.shapeType || "rectangle";
|
|
355
|
+
const strokeColorStr = highlight.content?.shape?.strokeColor || highlight.strokeColor || "#000000";
|
|
356
|
+
const strokeWidth = highlight.content?.shape?.strokeWidth || highlight.strokeWidth || 2;
|
|
357
|
+
const color = parseColor(strokeColorStr);
|
|
358
|
+
const { x, y, width, height } = scaledToPdfPoints(highlight.position.boundingRect, page);
|
|
359
|
+
switch (shapeType) {
|
|
360
|
+
case "rectangle":
|
|
361
|
+
page.drawRectangle({
|
|
362
|
+
x,
|
|
363
|
+
y,
|
|
364
|
+
width,
|
|
365
|
+
height,
|
|
366
|
+
borderColor: rgb(color.r, color.g, color.b),
|
|
367
|
+
borderWidth: strokeWidth,
|
|
368
|
+
opacity: color.a,
|
|
369
|
+
});
|
|
370
|
+
break;
|
|
371
|
+
case "circle":
|
|
372
|
+
page.drawEllipse({
|
|
373
|
+
x: x + width / 2,
|
|
374
|
+
y: y + height / 2,
|
|
375
|
+
xScale: width / 2,
|
|
376
|
+
yScale: height / 2,
|
|
377
|
+
borderColor: rgb(color.r, color.g, color.b),
|
|
378
|
+
borderWidth: strokeWidth,
|
|
379
|
+
opacity: color.a,
|
|
380
|
+
});
|
|
381
|
+
break;
|
|
382
|
+
case "arrow": {
|
|
383
|
+
// Use stored start/end points if available, otherwise default to left-to-right
|
|
384
|
+
const startPt = highlight.content?.shape?.startPoint;
|
|
385
|
+
const endPt = highlight.content?.shape?.endPoint;
|
|
386
|
+
// Calculate actual coordinates
|
|
387
|
+
// Note: PDF coordinates have Y going up, so we need to flip the Y
|
|
388
|
+
const startX = startPt ? x + startPt.x * width : x;
|
|
389
|
+
const startY = startPt ? y + (1 - startPt.y) * height : y + height / 2;
|
|
390
|
+
const endX = endPt ? x + endPt.x * width : x + width;
|
|
391
|
+
const endY = endPt ? y + (1 - endPt.y) * height : y + height / 2;
|
|
392
|
+
// Draw the main line
|
|
393
|
+
page.drawLine({
|
|
394
|
+
start: { x: startX, y: startY },
|
|
395
|
+
end: { x: endX, y: endY },
|
|
396
|
+
color: rgb(color.r, color.g, color.b),
|
|
397
|
+
thickness: strokeWidth,
|
|
398
|
+
opacity: color.a,
|
|
399
|
+
});
|
|
400
|
+
// Calculate arrowhead direction
|
|
401
|
+
const angle = Math.atan2(endY - startY, endX - startX);
|
|
402
|
+
const arrowSize = Math.min(15, width * 0.2, height * 0.4);
|
|
403
|
+
const arrowAngle = Math.PI / 6; // 30 degrees
|
|
404
|
+
// Draw arrowhead (two lines forming a V at the end)
|
|
405
|
+
page.drawLine({
|
|
406
|
+
start: {
|
|
407
|
+
x: endX - arrowSize * Math.cos(angle - arrowAngle),
|
|
408
|
+
y: endY - arrowSize * Math.sin(angle - arrowAngle),
|
|
409
|
+
},
|
|
410
|
+
end: { x: endX, y: endY },
|
|
411
|
+
color: rgb(color.r, color.g, color.b),
|
|
412
|
+
thickness: strokeWidth,
|
|
413
|
+
opacity: color.a,
|
|
414
|
+
});
|
|
415
|
+
page.drawLine({
|
|
416
|
+
start: {
|
|
417
|
+
x: endX - arrowSize * Math.cos(angle + arrowAngle),
|
|
418
|
+
y: endY - arrowSize * Math.sin(angle + arrowAngle),
|
|
419
|
+
},
|
|
420
|
+
end: { x: endX, y: endY },
|
|
421
|
+
color: rgb(color.r, color.g, color.b),
|
|
422
|
+
thickness: strokeWidth,
|
|
423
|
+
opacity: color.a,
|
|
424
|
+
});
|
|
425
|
+
break;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
/**
|
|
430
|
+
* Export a PDF with annotations embedded.
|
|
431
|
+
*
|
|
432
|
+
* @param pdfSource - The source PDF as a URL string, Uint8Array, or ArrayBuffer
|
|
433
|
+
* @param highlights - Array of highlights to embed in the PDF
|
|
434
|
+
* @param options - Export options for customizing colors and behavior
|
|
435
|
+
* @returns Promise<Uint8Array> - The modified PDF as bytes
|
|
436
|
+
*
|
|
437
|
+
* @example
|
|
438
|
+
* ```typescript
|
|
439
|
+
* const pdfBytes = await exportPdf(pdfUrl, highlights, {
|
|
440
|
+
* textHighlightColor: "rgba(255, 255, 0, 0.4)",
|
|
441
|
+
* onProgress: (current, total) => console.log(`${current}/${total} pages`)
|
|
442
|
+
* });
|
|
443
|
+
*
|
|
444
|
+
* // Download the file
|
|
445
|
+
* const blob = new Blob([pdfBytes], { type: "application/pdf" });
|
|
446
|
+
* const url = URL.createObjectURL(blob);
|
|
447
|
+
* const a = document.createElement("a");
|
|
448
|
+
* a.href = url;
|
|
449
|
+
* a.download = "annotated.pdf";
|
|
450
|
+
* a.click();
|
|
451
|
+
* URL.revokeObjectURL(url);
|
|
452
|
+
* ```
|
|
453
|
+
*
|
|
454
|
+
* @category Function
|
|
455
|
+
*/
|
|
456
|
+
export async function exportPdf(pdfSource, highlights, options = {}) {
|
|
457
|
+
// Load PDF
|
|
458
|
+
let pdfBytes;
|
|
459
|
+
if (typeof pdfSource === "string") {
|
|
460
|
+
const response = await fetch(pdfSource);
|
|
461
|
+
pdfBytes = await response.arrayBuffer();
|
|
462
|
+
}
|
|
463
|
+
else {
|
|
464
|
+
pdfBytes =
|
|
465
|
+
pdfSource instanceof Uint8Array
|
|
466
|
+
? pdfSource.buffer.slice(pdfSource.byteOffset, pdfSource.byteOffset + pdfSource.byteLength)
|
|
467
|
+
: pdfSource;
|
|
468
|
+
}
|
|
469
|
+
const pdfDoc = await PDFDocument.load(pdfBytes);
|
|
470
|
+
const pages = pdfDoc.getPages();
|
|
471
|
+
const font = await pdfDoc.embedFont(StandardFonts.Helvetica);
|
|
472
|
+
// Group by page and render
|
|
473
|
+
const byPage = groupByPage(highlights);
|
|
474
|
+
const totalPages = byPage.size;
|
|
475
|
+
let currentPage = 0;
|
|
476
|
+
for (const [pageNum, pageHighlights] of byPage) {
|
|
477
|
+
const page = pages[pageNum - 1]; // 1-indexed to 0-indexed
|
|
478
|
+
if (!page)
|
|
479
|
+
continue;
|
|
480
|
+
for (const highlight of pageHighlights) {
|
|
481
|
+
switch (highlight.type) {
|
|
482
|
+
case "text":
|
|
483
|
+
await renderTextHighlight(page, highlight, options);
|
|
484
|
+
break;
|
|
485
|
+
case "area":
|
|
486
|
+
await renderAreaHighlight(page, highlight, options);
|
|
487
|
+
break;
|
|
488
|
+
case "freetext":
|
|
489
|
+
await renderFreetextHighlight(page, highlight, options, font);
|
|
490
|
+
break;
|
|
491
|
+
case "image":
|
|
492
|
+
await renderImageHighlight(pdfDoc, page, highlight);
|
|
493
|
+
break;
|
|
494
|
+
case "drawing":
|
|
495
|
+
// Drawings are stored as PNG images, reuse image highlight rendering
|
|
496
|
+
await renderImageHighlight(pdfDoc, page, highlight);
|
|
497
|
+
break;
|
|
498
|
+
case "shape":
|
|
499
|
+
await renderShapeHighlight(page, highlight);
|
|
500
|
+
break;
|
|
501
|
+
default:
|
|
502
|
+
// Default to area highlight for backwards compatibility
|
|
503
|
+
await renderAreaHighlight(page, highlight, options);
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
currentPage++;
|
|
507
|
+
options.onProgress?.(currentPage, totalPages);
|
|
508
|
+
}
|
|
509
|
+
return pdfDoc.save();
|
|
510
|
+
}
|
|
511
|
+
//# sourceMappingURL=export-pdf.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"export-pdf.js","sourceRoot":"","sources":["../../../src/lib/export-pdf.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,GAAG,EAAE,aAAa,EAAoB,MAAM,SAAS,CAAC;AAyD5E;;GAEG;AACH,SAAS,UAAU,CAAC,KAAa;IAM/B,2CAA2C;IAC3C,MAAM,SAAS,GAAG,KAAK,CAAC,KAAK,CAC3B,mDAAmD,CACpD,CAAC;IACF,IAAI,SAAS,EAAE,CAAC;QACd,OAAO;YACL,CAAC,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG;YAC/B,CAAC,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG;YAC/B,CAAC,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG;YAC/B,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;SAC/C,CAAC;IACJ,CAAC;IAED,+BAA+B;IAC/B,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IACnC,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrB,OAAO;YACL,CAAC,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG;YACtC,CAAC,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG;YACtC,CAAC,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG;YACtC,CAAC,EAAE,CAAC;SACL,CAAC;IACJ,CAAC;IACD,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrB,OAAO;YACL,CAAC,EAAE,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG;YACtC,CAAC,EAAE,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG;YACtC,CAAC,EAAE,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG;YACtC,CAAC,EAAE,CAAC;SACL,CAAC;IACJ,CAAC;IAED,iBAAiB;IACjB,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC;AAC5C,CAAC;AAED;;;GAGG;AACH,SAAS,iBAAiB,CACxB,MAAc,EACd,IAAa;IAEb,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;IACjC,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;IAEnC,4BAA4B;IAC5B,MAAM,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC;IACvC,MAAM,MAAM,GAAG,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC;IAEzC,MAAM,CAAC,GAAG,MAAM,CAAC,EAAE,GAAG,MAAM,CAAC;IAC7B,MAAM,KAAK,GAAG,CAAC,MAAM,CAAC,EAAE,GAAG,MAAM,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC;IAC/C,MAAM,MAAM,GAAG,CAAC,MAAM,CAAC,EAAE,GAAG,MAAM,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC;IAEhD,gEAAgE;IAChE,MAAM,CAAC,GAAG,SAAS,GAAG,MAAM,CAAC,EAAE,GAAG,MAAM,GAAG,MAAM,CAAC;IAElD,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;AACjC,CAAC;AAED;;GAEG;AACH,SAAS,cAAc,CAAC,OAAe;IAIrC,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACrC,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;IAChC,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;IAChD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3C,KAAK,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IACtC,CAAC;IACD,MAAM,IAAI,GAAG,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC;IAC3D,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AACzB,CAAC;AAED;;;GAGG;AACH,SAAS,QAAQ,CACf,IAAY,EACZ,IAAa,EACb,QAAgB,EAChB,QAAgB;IAEhB,IAAI,CAAC,IAAI,IAAI,QAAQ,IAAI,CAAC;QAAE,OAAO,EAAE,CAAC;IAEtC,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,8DAA8D;IAC9D,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAEpC,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,EAAE,CAAC;YACtB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACf,SAAS;QACX,CAAC;QAED,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACrC,IAAI,WAAW,GAAG,EAAE,CAAC;QAErB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,QAAQ,GAAG,WAAW,CAAC,CAAC,CAAC,GAAG,WAAW,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;YAC/D,MAAM,SAAS,GAAG,IAAI,CAAC,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;YAE7D,IAAI,SAAS,IAAI,QAAQ,EAAE,CAAC;gBAC1B,WAAW,GAAG,QAAQ,CAAC;YACzB,CAAC;iBAAM,CAAC;gBACN,8BAA8B;gBAC9B,IAAI,WAAW,EAAE,CAAC;oBAChB,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;oBACxB,WAAW,GAAG,EAAE,CAAC;gBACnB,CAAC;gBAED,qEAAqE;gBACrE,IAAI,IAAI,CAAC,iBAAiB,CAAC,IAAI,EAAE,QAAQ,CAAC,GAAG,QAAQ,EAAE,CAAC;oBACtD,IAAI,SAAS,GAAG,IAAI,CAAC;oBACrB,OAAO,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;wBAC5B,IAAI,SAAS,GAAG,CAAC,CAAC;wBAClB,2CAA2C;wBAC3C,OACE,SAAS,GAAG,SAAS,CAAC,MAAM;4BAC5B,IAAI,CAAC,iBAAiB,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,EAAE,SAAS,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,IAAI,QAAQ,EACnF,CAAC;4BACD,SAAS,EAAE,CAAC;wBACd,CAAC;wBACD,MAAM,KAAK,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;wBAChD,SAAS,GAAG,SAAS,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;wBAE3C,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;4BACzB,gEAAgE;4BAChE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;wBACpB,CAAC;6BAAM,CAAC;4BACN,mEAAmE;4BACnE,WAAW,GAAG,KAAK,CAAC;wBACtB,CAAC;oBACH,CAAC;gBACH,CAAC;qBAAM,CAAC;oBACN,WAAW,GAAG,IAAI,CAAC;gBACrB,CAAC;YACH,CAAC;QACH,CAAC;QACD,IAAI,WAAW;YAAE,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC3C,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,SAAS,WAAW,CAClB,UAAiC;IAEjC,MAAM,GAAG,GAAG,IAAI,GAAG,EAAiC,CAAC;IACrD,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;QAC3B,MAAM,OAAO,GAAG,CAAC,CAAC,QAAQ,CAAC,YAAY,CAAC,UAAU,CAAC;QACnD,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC;YAAE,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QAC5C,GAAG,CAAC,GAAG,CAAC,OAAO,CAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC5B,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;GAGG;AACH,KAAK,UAAU,mBAAmB,CAChC,IAAa,EACb,SAA8B,EAC9B,OAAyB;IAEzB,sDAAsD;IACtD,MAAM,QAAQ,GACZ,SAAS,CAAC,cAAc;QACxB,OAAO,CAAC,kBAAkB;QAC1B,0BAA0B,CAAC;IAC7B,MAAM,KAAK,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;IACnC,MAAM,cAAc,GAAG,SAAS,CAAC,cAAc,IAAI,WAAW,CAAC;IAE/D,4DAA4D;IAC5D,MAAM,KAAK,GACT,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC;QACjC,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK;QAC1B,CAAC,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;IAExC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,iBAAiB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAE9D,IAAI,cAAc,KAAK,WAAW,EAAE,CAAC;YACnC,iDAAiD;YACjD,IAAI,CAAC,aAAa,CAAC;gBACjB,CAAC;gBACD,CAAC;gBACD,KAAK;gBACL,MAAM;gBACN,KAAK,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;gBACrC,OAAO,EAAE,KAAK,CAAC,CAAC;aACjB,CAAC,CAAC;QACL,CAAC;aAAM,IAAI,cAAc,KAAK,WAAW,EAAE,CAAC;YAC1C,mCAAmC;YACnC,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,GAAG,CAAC,CAAC;YAChD,IAAI,CAAC,aAAa,CAAC;gBACjB,CAAC;gBACD,CAAC;gBACD,KAAK;gBACL,MAAM,EAAE,aAAa;gBACrB,KAAK,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;gBACrC,OAAO,EAAE,KAAK,CAAC,CAAC;aACjB,CAAC,CAAC;QACL,CAAC;aAAM,IAAI,cAAc,KAAK,eAAe,EAAE,CAAC;YAC9C,wCAAwC;YACxC,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,GAAG,CAAC,CAAC;YAChD,MAAM,KAAK,GAAG,CAAC,GAAG,MAAM,GAAG,CAAC,GAAG,aAAa,GAAG,CAAC,CAAC;YACjD,IAAI,CAAC,aAAa,CAAC;gBACjB,CAAC;gBACD,CAAC,EAAE,KAAK;gBACR,KAAK;gBACL,MAAM,EAAE,aAAa;gBACrB,KAAK,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;gBACrC,OAAO,EAAE,KAAK,CAAC,CAAC;aACjB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;AACH,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,mBAAmB,CAChC,IAAa,EACb,SAA8B,EAC9B,OAAyB;IAEzB,sDAAsD;IACtD,MAAM,QAAQ,GACZ,SAAS,CAAC,cAAc;QACxB,OAAO,CAAC,kBAAkB;QAC1B,0BAA0B,CAAC;IAC7B,MAAM,KAAK,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;IACnC,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,iBAAiB,CAC/C,SAAS,CAAC,QAAQ,CAAC,YAAY,EAC/B,IAAI,CACL,CAAC;IAEF,IAAI,CAAC,aAAa,CAAC;QACjB,CAAC;QACD,CAAC;QACD,KAAK;QACL,MAAM;QACN,KAAK,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;QACrC,OAAO,EAAE,KAAK,CAAC,CAAC;KACjB,CAAC,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,KAAK,UAAU,uBAAuB,CACpC,IAAa,EACb,SAA8B,EAC9B,OAAyB,EACzB,IAAa;IAEb,MAAM,IAAI,GAAG,SAAS,CAAC,OAAO,EAAE,IAAI,IAAI,EAAE,CAAC;IAC3C,MAAM,SAAS,GAAG,UAAU,CAC1B,SAAS,CAAC,KAAK,IAAI,OAAO,CAAC,oBAAoB,IAAI,SAAS,CAC7D,CAAC;IAEF,mCAAmC;IACnC,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,iBAAiB,CAC/C,SAAS,CAAC,QAAQ,CAAC,YAAY,EAC/B,IAAI,CACL,CAAC;IAEF,iEAAiE;IACjE,2DAA2D;IAC3D,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;IACnC,MAAM,MAAM,GAAG,SAAS,GAAG,SAAS,CAAC,QAAQ,CAAC,YAAY,CAAC,MAAM,CAAC;IAClE,MAAM,cAAc,GAClB,QAAQ,CAAC,SAAS,CAAC,QAAQ,IAAI,EAAE,CAAC,IAAI,OAAO,CAAC,uBAAuB,IAAI,EAAE,CAAC;IAC9E,MAAM,QAAQ,GAAG,cAAc,GAAG,MAAM,CAAC;IAEzC,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE;QAC9B,cAAc;QACd,MAAM;QACN,QAAQ;QACR,aAAa,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE;QACtC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC;KAC5B,CAAC,CAAC;IAEH,wCAAwC;IACxC,MAAM,YAAY,GAAG,SAAS,CAAC,eAAe,IAAI,OAAO,CAAC,sBAAsB,IAAI,SAAS,CAAC;IAC9F,IAAI,YAAY,KAAK,aAAa,EAAE,CAAC;QACnC,MAAM,OAAO,GAAG,UAAU,CAAC,YAAY,CAAC,CAAC;QACzC,IAAI,CAAC,aAAa,CAAC;YACjB,CAAC;YACD,CAAC;YACD,KAAK;YACL,MAAM;YACN,KAAK,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;YAC3C,OAAO,EAAE,OAAO,CAAC,CAAC;SACnB,CAAC,CAAC;IACL,CAAC;IAED,wCAAwC;IACxC,MAAM,OAAO,GAAG,CAAC,GAAG,MAAM,CAAC;IAC3B,MAAM,QAAQ,GAAG,KAAK,GAAG,OAAO,GAAG,CAAC,CAAC;IACrC,MAAM,UAAU,GAAG,QAAQ,GAAG,GAAG,CAAC;IAElC,IAAI,QAAQ,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACvD,IAAI,QAAQ,GAAG,CAAC,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;QAE/C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,0CAA0C;YAC1C,IAAI,QAAQ,GAAG,CAAC,GAAG,OAAO;gBAAE,MAAM;YAElC,uCAAuC;YACvC,IAAI,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;gBAChB,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE;oBAClB,CAAC,EAAE,CAAC,GAAG,OAAO;oBACd,CAAC,EAAE,QAAQ;oBACX,IAAI,EAAE,QAAQ;oBACd,IAAI;oBACJ,KAAK,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC;iBAClD,CAAC,CAAC;YACL,CAAC;YAED,QAAQ,IAAI,UAAU,CAAC;QACzB,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,SAAS,yBAAyB,CAChC,IAAa,EACb,CAAS,EACT,CAAS,EACT,KAAa,EACb,MAAc;IAEd,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC;IAC1C,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,eAAe;IAClD,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,gBAAgB;IAErD,IAAI,QAAQ,KAAK,EAAE,EAAE,CAAC;QACpB,2CAA2C;QAC3C,gEAAgE;QAChE,OAAO;YACL,CAAC,EAAE,CAAC;YACJ,CAAC,EAAE,SAAS,GAAG,CAAC,GAAG,KAAK;YACxB,KAAK,EAAE,MAAM;YACb,MAAM,EAAE,KAAK;SACd,CAAC;IACJ,CAAC;SAAM,IAAI,QAAQ,KAAK,GAAG,EAAE,CAAC;QAC5B,gDAAgD;QAChD,OAAO;YACL,CAAC,EAAE,SAAS,GAAG,CAAC,GAAG,KAAK;YACxB,CAAC,EAAE,UAAU,GAAG,CAAC,GAAG,MAAM;YAC1B,KAAK;YACL,MAAM;SACP,CAAC;IACJ,CAAC;SAAM,IAAI,QAAQ,KAAK,GAAG,EAAE,CAAC;QAC5B,iCAAiC;QACjC,OAAO;YACL,CAAC,EAAE,UAAU,GAAG,CAAC,GAAG,MAAM;YAC1B,CAAC,EAAE,CAAC;YACJ,KAAK,EAAE,MAAM;YACb,MAAM,EAAE,KAAK;SACd,CAAC;IACJ,CAAC;IAED,gDAAgD;IAChD,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;AACjC,CAAC;AAED;;;;GAIG;AACH,KAAK,UAAU,oBAAoB,CACjC,MAAmB,EACnB,IAAa,EACb,SAA8B;IAE9B,MAAM,YAAY,GAAG,SAAS,CAAC,OAAO,EAAE,KAAK,CAAC;IAC9C,IAAI,CAAC,YAAY;QAAE,OAAO;IAE1B,IAAI,CAAC;QACH,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,cAAc,CAAC,YAAY,CAAC,CAAC;QACrD,MAAM,KAAK,GACT,IAAI,KAAK,KAAK;YACZ,CAAC,CAAC,MAAM,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;YAC9B,CAAC,CAAC,MAAM,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QAEnC,2EAA2E;QAC3E,MAAM,YAAY,GAAG,iBAAiB,CACpC,SAAS,CAAC,QAAQ,CAAC,YAAY,EAC/B,IAAI,CACL,CAAC;QAEF,+DAA+D;QAC/D,MAAM,SAAS,GAAG,yBAAyB,CACzC,IAAI,EACJ,YAAY,CAAC,CAAC,EACd,YAAY,CAAC,CAAC,EACd,YAAY,CAAC,KAAK,EAClB,YAAY,CAAC,MAAM,CACpB,CAAC;QAEF,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE;YAC3B,QAAQ,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,KAAK;YAClC,YAAY;YACZ,SAAS;SACV,CAAC,CAAC;QAEH,6CAA6C;QAC7C,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE;YACpB,CAAC,EAAE,SAAS,CAAC,CAAC;YACd,CAAC,EAAE,SAAS,CAAC,CAAC;YACd,KAAK,EAAE,SAAS,CAAC,KAAK;YACtB,MAAM,EAAE,SAAS,CAAC,MAAM;SACzB,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,wBAAwB,EAAE,KAAK,CAAC,CAAC;IACjD,CAAC;AACH,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,oBAAoB,CACjC,IAAa,EACb,SAA8B;IAE9B,sDAAsD;IACtD,MAAM,SAAS,GAAG,SAAS,CAAC,OAAO,EAAE,KAAK,EAAE,SAAS,IAAI,SAAS,CAAC,SAAS,IAAI,WAAW,CAAC;IAC5F,MAAM,cAAc,GAAG,SAAS,CAAC,OAAO,EAAE,KAAK,EAAE,WAAW,IAAI,SAAS,CAAC,WAAW,IAAI,SAAS,CAAC;IACnG,MAAM,WAAW,GAAG,SAAS,CAAC,OAAO,EAAE,KAAK,EAAE,WAAW,IAAI,SAAS,CAAC,WAAW,IAAI,CAAC,CAAC;IAExF,MAAM,KAAK,GAAG,UAAU,CAAC,cAAc,CAAC,CAAC;IACzC,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,iBAAiB,CAC/C,SAAS,CAAC,QAAQ,CAAC,YAAY,EAC/B,IAAI,CACL,CAAC;IAEF,QAAQ,SAAS,EAAE,CAAC;QAClB,KAAK,WAAW;YACd,IAAI,CAAC,aAAa,CAAC;gBACjB,CAAC;gBACD,CAAC;gBACD,KAAK;gBACL,MAAM;gBACN,WAAW,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;gBAC3C,WAAW,EAAE,WAAW;gBACxB,OAAO,EAAE,KAAK,CAAC,CAAC;aACjB,CAAC,CAAC;YACH,MAAM;QAER,KAAK,QAAQ;YACX,IAAI,CAAC,WAAW,CAAC;gBACf,CAAC,EAAE,CAAC,GAAG,KAAK,GAAG,CAAC;gBAChB,CAAC,EAAE,CAAC,GAAG,MAAM,GAAG,CAAC;gBACjB,MAAM,EAAE,KAAK,GAAG,CAAC;gBACjB,MAAM,EAAE,MAAM,GAAG,CAAC;gBAClB,WAAW,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;gBAC3C,WAAW,EAAE,WAAW;gBACxB,OAAO,EAAE,KAAK,CAAC,CAAC;aACjB,CAAC,CAAC;YACH,MAAM;QAER,KAAK,OAAO,CAAC,CAAC,CAAC;YACb,+EAA+E;YAC/E,MAAM,OAAO,GAAG,SAAS,CAAC,OAAO,EAAE,KAAK,EAAE,UAAU,CAAC;YACrD,MAAM,KAAK,GAAG,SAAS,CAAC,OAAO,EAAE,KAAK,EAAE,QAAQ,CAAC;YAEjD,+BAA+B;YAC/B,kEAAkE;YAClE,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;YACnD,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,GAAG,CAAC,CAAC;YACvE,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC;YACrD,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,GAAG,CAAC,CAAC;YAEjE,qBAAqB;YACrB,IAAI,CAAC,QAAQ,CAAC;gBACZ,KAAK,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE;gBAC/B,GAAG,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE;gBACzB,KAAK,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;gBACrC,SAAS,EAAE,WAAW;gBACtB,OAAO,EAAE,KAAK,CAAC,CAAC;aACjB,CAAC,CAAC;YAEH,gCAAgC;YAChC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,MAAM,EAAE,IAAI,GAAG,MAAM,CAAC,CAAC;YACvD,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,GAAG,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC,CAAC;YAC1D,MAAM,UAAU,GAAG,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,aAAa;YAE7C,oDAAoD;YACpD,IAAI,CAAC,QAAQ,CAAC;gBACZ,KAAK,EAAE;oBACL,CAAC,EAAE,IAAI,GAAG,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,UAAU,CAAC;oBAClD,CAAC,EAAE,IAAI,GAAG,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,UAAU,CAAC;iBACnD;gBACD,GAAG,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE;gBACzB,KAAK,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;gBACrC,SAAS,EAAE,WAAW;gBACtB,OAAO,EAAE,KAAK,CAAC,CAAC;aACjB,CAAC,CAAC;YACH,IAAI,CAAC,QAAQ,CAAC;gBACZ,KAAK,EAAE;oBACL,CAAC,EAAE,IAAI,GAAG,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,UAAU,CAAC;oBAClD,CAAC,EAAE,IAAI,GAAG,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,UAAU,CAAC;iBACnD;gBACD,GAAG,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE;gBACzB,KAAK,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;gBACrC,SAAS,EAAE,WAAW;gBACtB,OAAO,EAAE,KAAK,CAAC,CAAC;aACjB,CAAC,CAAC;YACH,MAAM;QACR,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,SAA4C,EAC5C,UAAiC,EACjC,UAA4B,EAAE;IAE9B,WAAW;IACX,IAAI,QAAqB,CAAC;IAC1B,IAAI,OAAO,SAAS,KAAK,QAAQ,EAAE,CAAC;QAClC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,SAAS,CAAC,CAAC;QACxC,QAAQ,GAAG,MAAM,QAAQ,CAAC,WAAW,EAAE,CAAC;IAC1C,CAAC;SAAM,CAAC;QACN,QAAQ;YACN,SAAS,YAAY,UAAU;gBAC7B,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CACpB,SAAS,CAAC,UAAU,EACpB,SAAS,CAAC,UAAU,GAAG,SAAS,CAAC,UAAU,CAC5C;gBACH,CAAC,CAAC,SAAS,CAAC;IAClB,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAChD,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;IAChC,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;IAE7D,2BAA2B;IAC3B,MAAM,MAAM,GAAG,WAAW,CAAC,UAAU,CAAC,CAAC;IACvC,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC;IAC/B,IAAI,WAAW,GAAG,CAAC,CAAC;IAEpB,KAAK,MAAM,CAAC,OAAO,EAAE,cAAc,CAAC,IAAI,MAAM,EAAE,CAAC;QAC/C,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,yBAAyB;QAC1D,IAAI,CAAC,IAAI;YAAE,SAAS;QAEpB,KAAK,MAAM,SAAS,IAAI,cAAc,EAAE,CAAC;YACvC,QAAQ,SAAS,CAAC,IAAI,EAAE,CAAC;gBACvB,KAAK,MAAM;oBACT,MAAM,mBAAmB,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;oBACpD,MAAM;gBACR,KAAK,MAAM;oBACT,MAAM,mBAAmB,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;oBACpD,MAAM;gBACR,KAAK,UAAU;oBACb,MAAM,uBAAuB,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;oBAC9D,MAAM;gBACR,KAAK,OAAO;oBACV,MAAM,oBAAoB,CAAC,MAAM,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;oBACpD,MAAM;gBACR,KAAK,SAAS;oBACZ,qEAAqE;oBACrE,MAAM,oBAAoB,CAAC,MAAM,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;oBACpD,MAAM;gBACR,KAAK,OAAO;oBACV,MAAM,oBAAoB,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;oBAC5C,MAAM;gBACR;oBACE,wDAAwD;oBACxD,MAAM,mBAAmB,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;YACxD,CAAC;QACH,CAAC;QAED,WAAW,EAAE,CAAC;QACd,OAAO,CAAC,UAAU,EAAE,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;IAChD,CAAC;IAED,OAAO,MAAM,CAAC,IAAI,EAAE,CAAC;AACvB,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
const getBoundingRect = (clientRects) => {
|
|
2
|
+
const rects = Array.from(clientRects).map((rect) => {
|
|
3
|
+
const { left, top, width, height, pageNumber } = rect;
|
|
4
|
+
const X0 = left;
|
|
5
|
+
const X1 = left + width;
|
|
6
|
+
const Y0 = top;
|
|
7
|
+
const Y1 = top + height;
|
|
8
|
+
return { X0, X1, Y0, Y1, pageNumber };
|
|
9
|
+
});
|
|
10
|
+
let firstPageNumber = Number.MAX_SAFE_INTEGER;
|
|
11
|
+
rects.forEach((rect) => {
|
|
12
|
+
firstPageNumber = Math.min(firstPageNumber, rect.pageNumber ?? firstPageNumber);
|
|
13
|
+
});
|
|
14
|
+
const rectsWithSizeOnFirstPage = rects.filter((rect) => (rect.X0 > 0 || rect.X1 > 0 || rect.Y0 > 0 || rect.Y1 > 0) &&
|
|
15
|
+
rect.pageNumber === firstPageNumber);
|
|
16
|
+
const optimal = rectsWithSizeOnFirstPage.reduce((res, rect) => {
|
|
17
|
+
return {
|
|
18
|
+
X0: Math.min(res.X0, rect.X0),
|
|
19
|
+
X1: Math.max(res.X1, rect.X1),
|
|
20
|
+
Y0: Math.min(res.Y0, rect.Y0),
|
|
21
|
+
Y1: Math.max(res.Y1, rect.Y1),
|
|
22
|
+
pageNumber: firstPageNumber,
|
|
23
|
+
};
|
|
24
|
+
}, rectsWithSizeOnFirstPage[0]);
|
|
25
|
+
const { X0, X1, Y0, Y1, pageNumber } = optimal;
|
|
26
|
+
return {
|
|
27
|
+
left: X0,
|
|
28
|
+
top: Y0,
|
|
29
|
+
width: X1 - X0,
|
|
30
|
+
height: Y1 - Y0,
|
|
31
|
+
pageNumber,
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
export default getBoundingRect;
|
|
35
|
+
//# sourceMappingURL=get-bounding-rect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-bounding-rect.js","sourceRoot":"","sources":["../../../src/lib/get-bounding-rect.ts"],"names":[],"mappings":"AAEA,MAAM,eAAe,GAAG,CAAC,WAAyB,EAAS,EAAE;IAC3D,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QACjD,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC;QAEtD,MAAM,EAAE,GAAG,IAAI,CAAC;QAChB,MAAM,EAAE,GAAG,IAAI,GAAG,KAAK,CAAC;QAExB,MAAM,EAAE,GAAG,GAAG,CAAC;QACf,MAAM,EAAE,GAAG,GAAG,GAAG,MAAM,CAAC;QAExB,OAAO,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,UAAU,EAAE,CAAC;IACxC,CAAC,CAAC,CAAC;IAEH,IAAI,eAAe,GAAG,MAAM,CAAC,gBAAgB,CAAC;IAE9C,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;QACrB,eAAe,GAAG,IAAI,CAAC,GAAG,CACxB,eAAe,EACf,IAAI,CAAC,UAAU,IAAI,eAAe,CACnC,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,wBAAwB,GAAG,KAAK,CAAC,MAAM,CAC3C,CAAC,IAAI,EAAE,EAAE,CACP,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,IAAI,IAAI,CAAC,EAAE,GAAG,CAAC,IAAI,IAAI,CAAC,EAAE,GAAG,CAAC,IAAI,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC;QAC1D,IAAI,CAAC,UAAU,KAAK,eAAe,CACtC,CAAC;IAEF,MAAM,OAAO,GAAG,wBAAwB,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE;QAC5D,OAAO;YACL,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,CAAC;YAC7B,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,CAAC;YAE7B,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,CAAC;YAC7B,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,CAAC;YAE7B,UAAU,EAAE,eAAe;SAC5B,CAAC;IACJ,CAAC,EAAE,wBAAwB,CAAC,CAAC,CAAC,CAAC,CAAC;IAEhC,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC;IAE/C,OAAO;QACL,IAAI,EAAE,EAAE;QACR,GAAG,EAAE,EAAE;QACP,KAAK,EAAE,EAAE,GAAG,EAAE;QACd,MAAM,EAAE,EAAE,GAAG,EAAE;QACf,UAAU;KACX,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,eAAe,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import optimizeClientRects from "./optimize-client-rects";
|
|
2
|
+
const isClientRectInsidePageRect = (clientRect, pageRect) => {
|
|
3
|
+
if (clientRect.top < pageRect.top) {
|
|
4
|
+
return false;
|
|
5
|
+
}
|
|
6
|
+
if (clientRect.bottom > pageRect.bottom) {
|
|
7
|
+
return false;
|
|
8
|
+
}
|
|
9
|
+
if (clientRect.right > pageRect.right) {
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
if (clientRect.left < pageRect.left) {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
return true;
|
|
16
|
+
};
|
|
17
|
+
const getClientRects = (range, pages, shouldOptimize = true) => {
|
|
18
|
+
const clientRects = Array.from(range.getClientRects());
|
|
19
|
+
const rects = [];
|
|
20
|
+
for (const clientRect of clientRects) {
|
|
21
|
+
for (const page of pages) {
|
|
22
|
+
const pageRect = page.node.getBoundingClientRect();
|
|
23
|
+
if (isClientRectInsidePageRect(clientRect, pageRect) &&
|
|
24
|
+
clientRect.width > 0 &&
|
|
25
|
+
clientRect.height > 0 &&
|
|
26
|
+
clientRect.width < pageRect.width &&
|
|
27
|
+
clientRect.left > pageRect.left &&
|
|
28
|
+
clientRect.height < pageRect.height) {
|
|
29
|
+
const highlightedRect = {
|
|
30
|
+
top: clientRect.top + page.node.scrollTop - pageRect.top,
|
|
31
|
+
left: clientRect.left + page.node.scrollLeft - pageRect.left,
|
|
32
|
+
width: clientRect.width,
|
|
33
|
+
height: clientRect.height,
|
|
34
|
+
pageNumber: page.number,
|
|
35
|
+
};
|
|
36
|
+
rects.push(highlightedRect);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return shouldOptimize ? optimizeClientRects(rects) : rects;
|
|
41
|
+
};
|
|
42
|
+
export default getClientRects;
|
|
43
|
+
//# sourceMappingURL=get-client-rects.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-client-rects.js","sourceRoot":"","sources":["../../../src/lib/get-client-rects.ts"],"names":[],"mappings":"AAEA,OAAO,mBAAmB,MAAM,yBAAyB,CAAC;AAE1D,MAAM,0BAA0B,GAAG,CAAC,UAAmB,EAAE,QAAiB,EAAE,EAAE;IAC5E,IAAI,UAAU,CAAC,GAAG,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC;QAClC,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,UAAU,CAAC,MAAM,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC;QACxC,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,UAAU,CAAC,KAAK,GAAG,QAAQ,CAAC,KAAK,EAAE,CAAC;QACtC,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,UAAU,CAAC,IAAI,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC;QACpC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAEF,MAAM,cAAc,GAAG,CACrB,KAAY,EACZ,KAAa,EACb,iBAA0B,IAAI,EAChB,EAAE;IAChB,MAAM,WAAW,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,cAAc,EAAE,CAAC,CAAC;IAEvD,MAAM,KAAK,GAAY,EAAE,CAAC;IAE1B,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;QACrC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,qBAAqB,EAAE,CAAC;YAEnD,IACE,0BAA0B,CAAC,UAAU,EAAE,QAAQ,CAAC;gBAChD,UAAU,CAAC,KAAK,GAAG,CAAC;gBACpB,UAAU,CAAC,MAAM,GAAG,CAAC;gBACrB,UAAU,CAAC,KAAK,GAAG,QAAQ,CAAC,KAAK;gBACjC,UAAU,CAAC,IAAI,GAAG,QAAQ,CAAC,IAAI;gBAC/B,UAAU,CAAC,MAAM,GAAG,QAAQ,CAAC,MAAM,EACnC,CAAC;gBACD,MAAM,eAAe,GAAG;oBACtB,GAAG,EAAE,UAAU,CAAC,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC,GAAG;oBACxD,IAAI,EAAE,UAAU,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,GAAG,QAAQ,CAAC,IAAI;oBAC5D,KAAK,EAAE,UAAU,CAAC,KAAK;oBACvB,MAAM,EAAE,UAAU,CAAC,MAAM;oBACzB,UAAU,EAAE,IAAI,CAAC,MAAM;iBACf,CAAC;gBAEX,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;YAC9B,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,cAAc,CAAC,CAAC,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;AAC7D,CAAC,CAAC;AAEF,eAAe,cAAc,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { GhostHighlight, Highlight } from "../types";
|
|
2
|
+
type GroupedHighlights = {
|
|
3
|
+
[pageNumber: number]: Array<Highlight | GhostHighlight>;
|
|
4
|
+
};
|
|
5
|
+
declare const groupHighlightsByPage: (highlights: Array<Highlight | GhostHighlight | null>) => GroupedHighlights;
|
|
6
|
+
export default groupHighlightsByPage;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
const groupHighlightsByPage = (highlights) => highlights.reduce((acc, highlight) => {
|
|
2
|
+
if (!highlight) {
|
|
3
|
+
return acc;
|
|
4
|
+
}
|
|
5
|
+
const pageNumbers = [
|
|
6
|
+
highlight.position.boundingRect.pageNumber,
|
|
7
|
+
...highlight.position.rects.map((rect) => rect.pageNumber || 0),
|
|
8
|
+
];
|
|
9
|
+
pageNumbers.forEach((pageNumber) => {
|
|
10
|
+
acc[pageNumber] ||= [];
|
|
11
|
+
const pageSpecificHighlight = {
|
|
12
|
+
...highlight,
|
|
13
|
+
position: {
|
|
14
|
+
...highlight.position,
|
|
15
|
+
rects: highlight.position.rects.filter((rect) => pageNumber === rect.pageNumber),
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
acc[pageNumber].push(pageSpecificHighlight);
|
|
19
|
+
});
|
|
20
|
+
return acc;
|
|
21
|
+
}, {});
|
|
22
|
+
export default groupHighlightsByPage;
|
|
23
|
+
//# sourceMappingURL=group-highlights-by-page.js.map
|