web-doc 0.12.0 → 0.13.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/dist/edit/pdf/engine/document.d.ts +3 -3
- package/dist/edit/pdf/engine/document.js +31 -17
- package/dist/edit/pdf/engine/existing-text.js +17 -3
- package/dist/edit/pdf/engine/layout.d.ts +2 -0
- package/dist/edit/pdf/engine/layout.js +26 -3
- package/dist/edit/pdf/engine/pdfium.d.ts +1 -0
- package/dist/edit/pdf/types.d.ts +23 -1
- package/dist/workers/pdf-edit-worker.js +72 -33
- package/package.json +1 -1
|
@@ -36,9 +36,9 @@ export declare class PdfEditDocument {
|
|
|
36
36
|
get pageCount(): number;
|
|
37
37
|
get pdfium(): Pdfium;
|
|
38
38
|
/**
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
39
|
+
* Preflights a batch against its starting document. Applying revalidates
|
|
40
|
+
* each operation against earlier changes in the batch; created-element
|
|
41
|
+
* references are checked once their targets exist.
|
|
42
42
|
*/
|
|
43
43
|
validate(operations: readonly PdfOrUnknownOperation[]): OperationIssue[];
|
|
44
44
|
/**
|
|
@@ -167,9 +167,9 @@ export class PdfEditDocument {
|
|
|
167
167
|
return this.#pdfium;
|
|
168
168
|
}
|
|
169
169
|
/**
|
|
170
|
-
*
|
|
171
|
-
*
|
|
172
|
-
*
|
|
170
|
+
* Preflights a batch against its starting document. Applying revalidates
|
|
171
|
+
* each operation against earlier changes in the batch; created-element
|
|
172
|
+
* references are checked once their targets exist.
|
|
173
173
|
*/
|
|
174
174
|
validate(operations) {
|
|
175
175
|
const issues = [];
|
|
@@ -229,7 +229,7 @@ export class PdfEditDocument {
|
|
|
229
229
|
if (!handler)
|
|
230
230
|
throw new ViewerError("internal", `Unknown pdf operation ${raw.op}`);
|
|
231
231
|
const context = this.#context(stateId, operationIndex);
|
|
232
|
-
const operation = this.#
|
|
232
|
+
const operation = this.#resolveAndValidate(raw, operationIndex, createdByOperation, handler, context);
|
|
233
233
|
const result = handler.apply(operation, context);
|
|
234
234
|
createdIds.push(...result.createdIds);
|
|
235
235
|
createdByOperation[operationIndex] = [...result.createdIds];
|
|
@@ -251,23 +251,23 @@ export class PdfEditDocument {
|
|
|
251
251
|
};
|
|
252
252
|
}
|
|
253
253
|
/**
|
|
254
|
-
*
|
|
255
|
-
*
|
|
256
|
-
*
|
|
257
|
-
* validation would have.
|
|
254
|
+
* Resolves a `"$<n>"` target, then checks every operation against the
|
|
255
|
+
* current document. Earlier operations may have moved, resized or removed
|
|
256
|
+
* an ordinary target since the batch's initial preflight.
|
|
258
257
|
*/
|
|
259
|
-
#
|
|
258
|
+
#resolveAndValidate(operation, operationIndex, createdByOperation, handler, context) {
|
|
260
259
|
const reference = referenceOf(operation);
|
|
261
|
-
if (reference === undefined)
|
|
262
|
-
return operation;
|
|
263
260
|
const issues = [];
|
|
264
261
|
const issue = issueCollector(operationIndex, issues);
|
|
265
|
-
|
|
266
|
-
if (
|
|
267
|
-
|
|
268
|
-
|
|
262
|
+
let resolved = operation;
|
|
263
|
+
if (reference !== undefined && "target" in operation) {
|
|
264
|
+
const id = createdByOperation[reference]?.[0];
|
|
265
|
+
if (id === undefined) {
|
|
266
|
+
issue("/target", "unknown-target", `Operation ${reference} created no element for "$${reference}"`);
|
|
267
|
+
throw invalidOperationError(issues);
|
|
268
|
+
}
|
|
269
|
+
resolved = { ...operation, target: id };
|
|
269
270
|
}
|
|
270
|
-
const resolved = { ...operation, target: id };
|
|
271
271
|
handler.validate(resolved, context, issue);
|
|
272
272
|
if (issues.length > 0)
|
|
273
273
|
throw invalidOperationError(issues);
|
|
@@ -888,7 +888,21 @@ export class PdfEditDocument {
|
|
|
888
888
|
const records = this.#objectsOf(pageIndex, page);
|
|
889
889
|
const { byObject, elements } = scanPage(this.#pdfium, page, textPage, pageIndex, geometry, records);
|
|
890
890
|
const offsets = this.#charOffsets(page, textPage, byObject, new Map(elements.map((element) => [element.id, element.text ?? ""])));
|
|
891
|
-
|
|
891
|
+
// A text box lays its lines out in the rect its mark keeps; only
|
|
892
|
+
// fresh marks are still on the records.
|
|
893
|
+
const frames = new Map();
|
|
894
|
+
for (const record of records)
|
|
895
|
+
if (record.mark?.kind === "textBox" && !frames.has(record.id))
|
|
896
|
+
frames.set(record.id, roundRect(record.mark.rect));
|
|
897
|
+
return use({
|
|
898
|
+
page,
|
|
899
|
+
textPage,
|
|
900
|
+
geometry,
|
|
901
|
+
byObject,
|
|
902
|
+
elements,
|
|
903
|
+
offsets,
|
|
904
|
+
frames,
|
|
905
|
+
});
|
|
892
906
|
});
|
|
893
907
|
}
|
|
894
908
|
#withPage(pageIndex, use) {
|
|
@@ -169,16 +169,30 @@ function replaceInPlace(context, target, text) {
|
|
|
169
169
|
context.withPage(target.location.pageIndex, (page) => {
|
|
170
170
|
setText(pdfium, lib.FPDFPage_GetObject(page, index), text);
|
|
171
171
|
});
|
|
172
|
-
const
|
|
172
|
+
const faithful = context.withPage(target.location.pageIndex, (page) => {
|
|
173
173
|
const textPage = lib.FPDFText_LoadPage(page);
|
|
174
174
|
try {
|
|
175
|
-
|
|
175
|
+
const object = lib.FPDFPage_GetObject(page, index);
|
|
176
|
+
const readBack = pdfium.readWideString((buffer, bytes) => lib.FPDFTextObj_GetText(object, textPage, buffer, bytes));
|
|
177
|
+
if (readBack === text)
|
|
178
|
+
return true;
|
|
179
|
+
// Reading-order extraction can append a generated gap before the next
|
|
180
|
+
// object. Verify the object's own characters instead, retaining every
|
|
181
|
+
// authored space: trimming would also hide a lost deliberate space.
|
|
182
|
+
let authored = "";
|
|
183
|
+
const count = lib.FPDFText_CountChars(textPage);
|
|
184
|
+
for (let at = 0; at < count; at += 1) {
|
|
185
|
+
if (lib.FPDFText_GetTextObject(textPage, at) === object &&
|
|
186
|
+
lib.FPDFText_IsGenerated(textPage, at) === 0)
|
|
187
|
+
authored += String.fromCodePoint(lib.FPDFText_GetUnicode(textPage, at));
|
|
188
|
+
}
|
|
189
|
+
return authored === text;
|
|
176
190
|
}
|
|
177
191
|
finally {
|
|
178
192
|
lib.FPDFText_ClosePage(textPage);
|
|
179
193
|
}
|
|
180
194
|
});
|
|
181
|
-
if (
|
|
195
|
+
if (faithful)
|
|
182
196
|
return true;
|
|
183
197
|
// Put the old text back so the fallback path starts from a known state.
|
|
184
198
|
context.withPage(target.location.pageIndex, (page) => {
|
|
@@ -12,6 +12,8 @@ export interface TextPageScan {
|
|
|
12
12
|
readonly elements: readonly PdfElement[];
|
|
13
13
|
/** Per character of the text page: its element and offset, when an object draws it. */
|
|
14
14
|
readonly offsets: readonly (TextPosition | undefined)[];
|
|
15
|
+
/** Element id → the rectangle its text is laid out in, for text boxes. */
|
|
16
|
+
readonly frames?: ReadonlyMap<string, PageRect>;
|
|
15
17
|
}
|
|
16
18
|
/** The layout of one element, or `undefined` when it draws no text. */
|
|
17
19
|
export declare function layoutOf(pdfium: Pdfium, scan: TextPageScan, element: PdfElement): TextLayout | undefined;
|
|
@@ -8,10 +8,12 @@ export function layoutOf(pdfium, scan, element) {
|
|
|
8
8
|
if (!TEXT_KINDS.has(element.kind))
|
|
9
9
|
return undefined;
|
|
10
10
|
const glyphs = glyphsOf(pdfium, scan, (position) => position.elementId === element.id);
|
|
11
|
+
const lines = linesOf(pdfium, scan, glyphs);
|
|
11
12
|
return {
|
|
12
13
|
elementId: element.id,
|
|
13
14
|
pageIndex: element.pageIndex,
|
|
14
|
-
|
|
15
|
+
frame: frameOf(scan, element, lines),
|
|
16
|
+
lines,
|
|
15
17
|
};
|
|
16
18
|
}
|
|
17
19
|
/** The layouts of every text element of the page, in reading order, from one pass. */
|
|
@@ -30,14 +32,30 @@ export function layoutsOf(pdfium, scan) {
|
|
|
30
32
|
const own = byElement.get(element.id);
|
|
31
33
|
if (!own || !TEXT_KINDS.has(element.kind))
|
|
32
34
|
continue;
|
|
35
|
+
const lines = linesOf(pdfium, scan, own);
|
|
33
36
|
layouts.push({
|
|
34
37
|
elementId: element.id,
|
|
35
38
|
pageIndex: element.pageIndex,
|
|
36
|
-
|
|
39
|
+
frame: frameOf(scan, element, lines),
|
|
40
|
+
lines,
|
|
37
41
|
});
|
|
38
42
|
}
|
|
39
43
|
return layouts;
|
|
40
44
|
}
|
|
45
|
+
/**
|
|
46
|
+
* The box an element's text is laid out in: a paragraph's frame (its bounds
|
|
47
|
+
* already start at the pen and span its widest advance), a text box's own
|
|
48
|
+
* rect, else the union of the lines' advance boxes.
|
|
49
|
+
*/
|
|
50
|
+
function frameOf(scan, element, lines) {
|
|
51
|
+
if (element.kind === "paragraph")
|
|
52
|
+
return element.bounds;
|
|
53
|
+
const own = scan.frames?.get(element.id);
|
|
54
|
+
if (own)
|
|
55
|
+
return own;
|
|
56
|
+
const boxes = lines.flatMap((line) => line.advanceBounds ? [line.advanceBounds] : []);
|
|
57
|
+
return boxes.length > 0 ? roundRect(unionRects(boxes)) : element.bounds;
|
|
58
|
+
}
|
|
41
59
|
/** The caret position nearest to a page-space point, or none without text. */
|
|
42
60
|
export function positionIn(pdfium, scan, point) {
|
|
43
61
|
const glyphs = glyphsOf(pdfium, scan, () => true);
|
|
@@ -105,6 +123,7 @@ function glyphsOf(pdfium, scan, keep) {
|
|
|
105
123
|
position,
|
|
106
124
|
char: String.fromCodePoint(lib.FPDFText_GetUnicode(textPage, index)),
|
|
107
125
|
box: roundRect(userRectToPage(geometry, left, bottom, right, top)),
|
|
126
|
+
loose: roundRect(userRectToPage(geometry, looseLeft, looseBottom, looseRight, looseTop)),
|
|
108
127
|
advance: round(Math.abs(looseRight - looseLeft)),
|
|
109
128
|
origin: roundPoint(userToPage(geometry, origin[0], origin[1])),
|
|
110
129
|
});
|
|
@@ -136,11 +155,15 @@ function linesOf(pdfium, scan, glyphs) {
|
|
|
136
155
|
},
|
|
137
156
|
text: members.map((glyph) => glyph.char).join(""),
|
|
138
157
|
bounds: roundRect(unionRects(members.map((glyph) => glyph.box))),
|
|
158
|
+
// PDFium's loose boxes run from each origin to origin plus advance,
|
|
159
|
+
// ascent to descent: their union is the line a text field must hold.
|
|
160
|
+
advanceBounds: roundRect(unionRects(members.map((glyph) => glyph.loose))),
|
|
139
161
|
baseline: members[0].origin,
|
|
140
|
-
glyphs: members.map(({ position, box, advance }) => ({
|
|
162
|
+
glyphs: members.map(({ position, box, advance, origin }) => ({
|
|
141
163
|
offset: position.offset,
|
|
142
164
|
box,
|
|
143
165
|
advance,
|
|
166
|
+
origin,
|
|
144
167
|
})),
|
|
145
168
|
fontFamily: style.fontFamily,
|
|
146
169
|
fontSize: style.fontSize,
|
|
@@ -75,6 +75,7 @@ export interface PdfiumFunctions {
|
|
|
75
75
|
FPDFText_GetCharBox(textPage: number, index: number, left: number, right: number, bottom: number, top: number): boolean;
|
|
76
76
|
FPDFText_GetTextObject(textPage: number, index: number): number;
|
|
77
77
|
FPDFText_GetUnicode(textPage: number, index: number): number;
|
|
78
|
+
FPDFText_IsGenerated(textPage: number, index: number): number;
|
|
78
79
|
FPDFText_GetCharIndexFromTextIndex(textPage: number, textIndex: number): number;
|
|
79
80
|
/** Advance box of a character as an FS_RECTF {left, top, right, bottom} of floats. */
|
|
80
81
|
FPDFText_GetLooseCharBox(textPage: number, index: number, rect: number): boolean;
|
package/dist/edit/pdf/types.d.ts
CHANGED
|
@@ -255,6 +255,12 @@ export interface TextLayoutGlyph {
|
|
|
255
255
|
readonly box: PageRect;
|
|
256
256
|
/** Advance width along the baseline, in points. */
|
|
257
257
|
readonly advance: number;
|
|
258
|
+
/**
|
|
259
|
+
* Pen position on the baseline where the glyph starts, in page space. The
|
|
260
|
+
* steps between neighbours are the advances the file draws with, character
|
|
261
|
+
* and word spacing and TJ kerning included.
|
|
262
|
+
*/
|
|
263
|
+
readonly origin?: PagePoint;
|
|
258
264
|
}
|
|
259
265
|
/** One line of a text element: one PDFium text object, as the file stores it. */
|
|
260
266
|
export interface TextLayoutLine {
|
|
@@ -263,6 +269,15 @@ export interface TextLayoutLine {
|
|
|
263
269
|
readonly text: string;
|
|
264
270
|
/** Union of the glyph boxes, in page space. */
|
|
265
271
|
readonly bounds: PageRect;
|
|
272
|
+
/**
|
|
273
|
+
* The box the line's advances fill, the size a text field needs to hold the
|
|
274
|
+
* line unwrapped: from the first glyph's origin to the last glyph's origin
|
|
275
|
+
* plus its advance, and from the font's ascent to its descent at the line's
|
|
276
|
+
* size. It differs from `bounds` by the glyphs' side bearings, usually
|
|
277
|
+
* wider; in page space and axis-aligned like `bounds`, so it turns with the
|
|
278
|
+
* text.
|
|
279
|
+
*/
|
|
280
|
+
readonly advanceBounds?: PageRect;
|
|
266
281
|
/** Start of the baseline, in page space. */
|
|
267
282
|
readonly baseline: PagePoint;
|
|
268
283
|
readonly glyphs: readonly TextLayoutGlyph[];
|
|
@@ -305,10 +320,17 @@ export interface TextFont {
|
|
|
305
320
|
*/
|
|
306
321
|
readonly missing?: "not-embedded" | "cid-keyed" | "type1" | "no-unicode" | "unreadable";
|
|
307
322
|
}
|
|
308
|
-
/** The drawn geometry of a `text`, `textBox` or `table` element. */
|
|
323
|
+
/** The drawn geometry of a `text`, `textBox`, `paragraph` or `table` element. */
|
|
309
324
|
export interface TextLayout {
|
|
310
325
|
readonly elementId: string;
|
|
311
326
|
readonly pageIndex: number;
|
|
327
|
+
/**
|
|
328
|
+
* The box the element's text is laid out in, in page space: a text box's or
|
|
329
|
+
* a paragraph's own rectangle, otherwise the union of its lines'
|
|
330
|
+
* `advanceBounds`. Place an inline text field here rather than on the ink
|
|
331
|
+
* `bounds`, which a browser's advance-based layout outgrows.
|
|
332
|
+
*/
|
|
333
|
+
readonly frame?: PageRect;
|
|
312
334
|
/** Lines in reading order: a text box's lines, a table's cells. */
|
|
313
335
|
readonly lines: readonly TextLayoutLine[];
|
|
314
336
|
}
|
|
@@ -6759,10 +6759,12 @@ function layoutOf(pdfium, scan, element) {
|
|
|
6759
6759
|
scan,
|
|
6760
6760
|
(position) => position.elementId === element.id
|
|
6761
6761
|
);
|
|
6762
|
+
const lines = linesOf(pdfium, scan, glyphs);
|
|
6762
6763
|
return {
|
|
6763
6764
|
elementId: element.id,
|
|
6764
6765
|
pageIndex: element.pageIndex,
|
|
6765
|
-
|
|
6766
|
+
frame: frameOf(scan, element, lines),
|
|
6767
|
+
lines
|
|
6766
6768
|
};
|
|
6767
6769
|
}
|
|
6768
6770
|
function layoutsOf(pdfium, scan) {
|
|
@@ -6777,14 +6779,25 @@ function layoutsOf(pdfium, scan) {
|
|
|
6777
6779
|
for (const element of scan.elements) {
|
|
6778
6780
|
const own = byElement.get(element.id);
|
|
6779
6781
|
if (!own || !TEXT_KINDS.has(element.kind)) continue;
|
|
6782
|
+
const lines = linesOf(pdfium, scan, own);
|
|
6780
6783
|
layouts.push({
|
|
6781
6784
|
elementId: element.id,
|
|
6782
6785
|
pageIndex: element.pageIndex,
|
|
6783
|
-
|
|
6786
|
+
frame: frameOf(scan, element, lines),
|
|
6787
|
+
lines
|
|
6784
6788
|
});
|
|
6785
6789
|
}
|
|
6786
6790
|
return layouts;
|
|
6787
6791
|
}
|
|
6792
|
+
function frameOf(scan, element, lines) {
|
|
6793
|
+
if (element.kind === "paragraph") return element.bounds;
|
|
6794
|
+
const own = scan.frames?.get(element.id);
|
|
6795
|
+
if (own) return own;
|
|
6796
|
+
const boxes = lines.flatMap(
|
|
6797
|
+
(line) => line.advanceBounds ? [line.advanceBounds] : []
|
|
6798
|
+
);
|
|
6799
|
+
return boxes.length > 0 ? roundRect(unionRects(boxes)) : element.bounds;
|
|
6800
|
+
}
|
|
6788
6801
|
function positionIn(pdfium, scan, point) {
|
|
6789
6802
|
const glyphs = glyphsOf(pdfium, scan, () => true);
|
|
6790
6803
|
if (glyphs.length === 0) return void 0;
|
|
@@ -6859,6 +6872,9 @@ function glyphsOf(pdfium, scan, keep) {
|
|
|
6859
6872
|
position,
|
|
6860
6873
|
char: String.fromCodePoint(lib.FPDFText_GetUnicode(textPage, index)),
|
|
6861
6874
|
box: roundRect(userRectToPage(geometry, left, bottom, right, top)),
|
|
6875
|
+
loose: roundRect(
|
|
6876
|
+
userRectToPage(geometry, looseLeft, looseBottom, looseRight, looseTop)
|
|
6877
|
+
),
|
|
6862
6878
|
advance: round(Math.abs(looseRight - looseLeft)),
|
|
6863
6879
|
origin: roundPoint(userToPage(geometry, origin[0], origin[1]))
|
|
6864
6880
|
});
|
|
@@ -6886,11 +6902,15 @@ function linesOf(pdfium, scan, glyphs) {
|
|
|
6886
6902
|
},
|
|
6887
6903
|
text: members.map((glyph) => glyph.char).join(""),
|
|
6888
6904
|
bounds: roundRect(unionRects(members.map((glyph) => glyph.box))),
|
|
6905
|
+
// PDFium's loose boxes run from each origin to origin plus advance,
|
|
6906
|
+
// ascent to descent: their union is the line a text field must hold.
|
|
6907
|
+
advanceBounds: roundRect(unionRects(members.map((glyph) => glyph.loose))),
|
|
6889
6908
|
baseline: members[0].origin,
|
|
6890
|
-
glyphs: members.map(({ position, box, advance: advance2 }) => ({
|
|
6909
|
+
glyphs: members.map(({ position, box, advance: advance2, origin }) => ({
|
|
6891
6910
|
offset: position.offset,
|
|
6892
6911
|
box,
|
|
6893
|
-
advance: advance2
|
|
6912
|
+
advance: advance2,
|
|
6913
|
+
origin
|
|
6894
6914
|
})),
|
|
6895
6915
|
fontFamily: style.fontFamily,
|
|
6896
6916
|
fontSize: style.fontSize,
|
|
@@ -9997,22 +10017,28 @@ function replaceInPlace(context, target, text) {
|
|
|
9997
10017
|
context.withPage(target.location.pageIndex, (page) => {
|
|
9998
10018
|
setText(pdfium, lib.FPDFPage_GetObject(page, index), text);
|
|
9999
10019
|
});
|
|
10000
|
-
const
|
|
10020
|
+
const faithful = context.withPage(target.location.pageIndex, (page) => {
|
|
10001
10021
|
const textPage = lib.FPDFText_LoadPage(page);
|
|
10002
10022
|
try {
|
|
10003
|
-
|
|
10004
|
-
|
|
10005
|
-
|
|
10006
|
-
textPage,
|
|
10007
|
-
buffer,
|
|
10008
|
-
bytes2
|
|
10009
|
-
)
|
|
10023
|
+
const object = lib.FPDFPage_GetObject(page, index);
|
|
10024
|
+
const readBack = pdfium.readWideString(
|
|
10025
|
+
(buffer, bytes2) => lib.FPDFTextObj_GetText(object, textPage, buffer, bytes2)
|
|
10010
10026
|
);
|
|
10027
|
+
if (readBack === text) return true;
|
|
10028
|
+
let authored = "";
|
|
10029
|
+
const count = lib.FPDFText_CountChars(textPage);
|
|
10030
|
+
for (let at = 0; at < count; at += 1) {
|
|
10031
|
+
if (lib.FPDFText_GetTextObject(textPage, at) === object && lib.FPDFText_IsGenerated(textPage, at) === 0)
|
|
10032
|
+
authored += String.fromCodePoint(
|
|
10033
|
+
lib.FPDFText_GetUnicode(textPage, at)
|
|
10034
|
+
);
|
|
10035
|
+
}
|
|
10036
|
+
return authored === text;
|
|
10011
10037
|
} finally {
|
|
10012
10038
|
lib.FPDFText_ClosePage(textPage);
|
|
10013
10039
|
}
|
|
10014
10040
|
});
|
|
10015
|
-
if (
|
|
10041
|
+
if (faithful) return true;
|
|
10016
10042
|
context.withPage(target.location.pageIndex, (page) => {
|
|
10017
10043
|
setText(pdfium, lib.FPDFPage_GetObject(page, index), previous);
|
|
10018
10044
|
});
|
|
@@ -11500,9 +11526,9 @@ var PdfEditDocument = class {
|
|
|
11500
11526
|
return this.#pdfium;
|
|
11501
11527
|
}
|
|
11502
11528
|
/**
|
|
11503
|
-
*
|
|
11504
|
-
*
|
|
11505
|
-
*
|
|
11529
|
+
* Preflights a batch against its starting document. Applying revalidates
|
|
11530
|
+
* each operation against earlier changes in the batch; created-element
|
|
11531
|
+
* references are checked once their targets exist.
|
|
11506
11532
|
*/
|
|
11507
11533
|
validate(operations) {
|
|
11508
11534
|
const issues = [];
|
|
@@ -11558,7 +11584,7 @@ var PdfEditDocument = class {
|
|
|
11558
11584
|
if (!handler)
|
|
11559
11585
|
throw new ViewerError("internal", `Unknown pdf operation ${raw.op}`);
|
|
11560
11586
|
const context = this.#context(stateId, operationIndex);
|
|
11561
|
-
const operation2 = this.#
|
|
11587
|
+
const operation2 = this.#resolveAndValidate(
|
|
11562
11588
|
raw,
|
|
11563
11589
|
operationIndex,
|
|
11564
11590
|
createdByOperation,
|
|
@@ -11585,26 +11611,27 @@ var PdfEditDocument = class {
|
|
|
11585
11611
|
};
|
|
11586
11612
|
}
|
|
11587
11613
|
/**
|
|
11588
|
-
*
|
|
11589
|
-
*
|
|
11590
|
-
*
|
|
11591
|
-
* validation would have.
|
|
11614
|
+
* Resolves a `"$<n>"` target, then checks every operation against the
|
|
11615
|
+
* current document. Earlier operations may have moved, resized or removed
|
|
11616
|
+
* an ordinary target since the batch's initial preflight.
|
|
11592
11617
|
*/
|
|
11593
|
-
#
|
|
11618
|
+
#resolveAndValidate(operation2, operationIndex, createdByOperation, handler, context) {
|
|
11594
11619
|
const reference = referenceOf(operation2);
|
|
11595
|
-
if (reference === void 0) return operation2;
|
|
11596
11620
|
const issues = [];
|
|
11597
11621
|
const issue = issueCollector(operationIndex, issues);
|
|
11598
|
-
|
|
11599
|
-
if (
|
|
11600
|
-
|
|
11601
|
-
|
|
11602
|
-
|
|
11603
|
-
|
|
11604
|
-
|
|
11605
|
-
|
|
11622
|
+
let resolved = operation2;
|
|
11623
|
+
if (reference !== void 0 && "target" in operation2) {
|
|
11624
|
+
const id = createdByOperation[reference]?.[0];
|
|
11625
|
+
if (id === void 0) {
|
|
11626
|
+
issue(
|
|
11627
|
+
"/target",
|
|
11628
|
+
"unknown-target",
|
|
11629
|
+
`Operation ${reference} created no element for "$${reference}"`
|
|
11630
|
+
);
|
|
11631
|
+
throw invalidOperationError(issues);
|
|
11632
|
+
}
|
|
11633
|
+
resolved = { ...operation2, target: id };
|
|
11606
11634
|
}
|
|
11607
|
-
const resolved = { ...operation2, target: id };
|
|
11608
11635
|
handler.validate(resolved, context, issue);
|
|
11609
11636
|
if (issues.length > 0) throw invalidOperationError(issues);
|
|
11610
11637
|
return resolved;
|
|
@@ -12238,7 +12265,19 @@ var PdfEditDocument = class {
|
|
|
12238
12265
|
byObject,
|
|
12239
12266
|
new Map(elements.map((element) => [element.id, element.text ?? ""]))
|
|
12240
12267
|
);
|
|
12241
|
-
|
|
12268
|
+
const frames = /* @__PURE__ */ new Map();
|
|
12269
|
+
for (const record of records)
|
|
12270
|
+
if (record.mark?.kind === "textBox" && !frames.has(record.id))
|
|
12271
|
+
frames.set(record.id, roundRect(record.mark.rect));
|
|
12272
|
+
return use({
|
|
12273
|
+
page,
|
|
12274
|
+
textPage,
|
|
12275
|
+
geometry,
|
|
12276
|
+
byObject,
|
|
12277
|
+
elements,
|
|
12278
|
+
offsets,
|
|
12279
|
+
frames
|
|
12280
|
+
});
|
|
12242
12281
|
});
|
|
12243
12282
|
}
|
|
12244
12283
|
#withPage(pageIndex, use) {
|